From f026017255bb8fc6c0cdfa46ad1fb58daeb48c35 Mon Sep 17 00:00:00 2001 From: gsherman Date: Sat, 24 Jan 2004 16:44:01 +0000 Subject: [PATCH] First fully functional version of the buffer (geoprocessing) plugin git-svn-id: http://svn.osgeo.org/qgis/trunk@570 c8812cc2-4d05-0410-92ff-de0c093fc19c --- plugins/geoprocessing/Makefile.am | 3 +- plugins/geoprocessing/qgsdlgpgbuffer.cpp | 131 ++++++++----- plugins/geoprocessing/qgsdlgpgbuffer.h | 72 +++++-- plugins/geoprocessing/qgspggeoprocessing.cpp | 187 ++++++++++++------- plugins/geoprocessing/qgspggeoprocessing.h | 78 ++++---- 5 files changed, 300 insertions(+), 171 deletions(-) diff --git a/plugins/geoprocessing/Makefile.am b/plugins/geoprocessing/Makefile.am index dec2208101e..47d24c5126f 100644 --- a/plugins/geoprocessing/Makefile.am +++ b/plugins/geoprocessing/Makefile.am @@ -9,7 +9,7 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # $Id$ - +if POSTGRESDB lib_LTLIBRARIES = libpggeoprocessingplugin.la %.moc.cpp: %.h $(MOC) -o $@ $< @@ -48,3 +48,4 @@ BUILT_SOURCES = $(pggeoprocessing_MOC) $(pggeoprocessing_UI) AM_CXXFLAGS := $(CXXFLAGS) $(EXTRA_CXXFLAGS) $(QT_CXXFLAGS) $(PGDB) -I$(PG_INC) libpggeoprocessingplugin_la_LIBADD = $(QT_LDADD) $(PG_LIB) +endif diff --git a/plugins/geoprocessing/qgsdlgpgbuffer.cpp b/plugins/geoprocessing/qgsdlgpgbuffer.cpp index e8ee0418255..7ee5b7c47f2 100644 --- a/plugins/geoprocessing/qgsdlgpgbuffer.cpp +++ b/plugins/geoprocessing/qgsdlgpgbuffer.cpp @@ -1,53 +1,98 @@ +/*************************************************************************** + qgsdlgbuffer.cpp + Buffer dialog - Subclasses qgsdlgbufferbase + Part of the Geoprocessing plugin for PostgreSQL/PostGIS layers + ------------------- + begin : Jan 21, 2004 + copyright : (C) 2004 by Gary E.Sherman + email : sherman at mrcc.com + + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + /* $Id$ */ #include #include #include #include #include "qgsdlgpgbuffer.h" -QgsDlgPgBuffer::QgsDlgPgBuffer(QWidget *parent, const char *name) - :QgsDlgPgBufferBase(parent,name){ -} -QgsDlgPgBuffer::~QgsDlgPgBuffer(){ -} -void QgsDlgPgBuffer::setBufferLabel(QString &lbl){ - lblBufferInfo->setText(lbl); -} -QString QgsDlgPgBuffer::bufferDistance(){ - return txtBufferDistance->text(); -} -QString QgsDlgPgBuffer::bufferLayerName(){ - return txtBufferedLayerName->text(); -} -bool QgsDlgPgBuffer::addLayerToMap(){ - return chkAddToMap->isChecked(); -} -QString QgsDlgPgBuffer::geometryColumn(){ - return txtGeometryColumn->text(); -} -QString QgsDlgPgBuffer::srid(){ - return txtSrid->text(); -} -QString QgsDlgPgBuffer::objectIdColumn(){ - return cmbFields->currentText(); -} -QString QgsDlgPgBuffer::schema(){ - return cmbSchema->currentText(); -} -void QgsDlgPgBuffer::addFieldItem(QString field){ - cmbFields->insertItem(field); -} -void QgsDlgPgBuffer::addSchema(QString schema){ - cmbSchema->insertItem(schema); -} -void QgsDlgPgBuffer::setSrid(QString srid){ - txtSrid->setText(srid); -} -void QgsDlgPgBuffer::setBufferLayerName(QString name){ - txtBufferedLayerName->setText(name); -} -void QgsDlgPgBuffer::setGeometryColumn(QString name){ - txtGeometryColumn->setText(name); +QgsDlgPgBuffer::QgsDlgPgBuffer(QWidget * parent, const char *name) +:QgsDlgPgBufferBase(parent, name) +{ } +QgsDlgPgBuffer::~QgsDlgPgBuffer() +{ +} +void QgsDlgPgBuffer::setBufferLabel(QString & lbl) +{ + lblBufferInfo->setText(lbl); +} +QString QgsDlgPgBuffer::bufferDistance() +{ + return txtBufferDistance->text(); +} + +QString QgsDlgPgBuffer::bufferLayerName() +{ + return txtBufferedLayerName->text(); +} + +bool QgsDlgPgBuffer::addLayerToMap() +{ + return chkAddToMap->isChecked(); +} + +QString QgsDlgPgBuffer::geometryColumn() +{ + return txtGeometryColumn->text(); +} + +QString QgsDlgPgBuffer::srid() +{ + return txtSrid->text(); +} + +QString QgsDlgPgBuffer::objectIdColumn() +{ + return cmbFields->currentText(); +} + +QString QgsDlgPgBuffer::schema() +{ + return cmbSchema->currentText(); +} + +void QgsDlgPgBuffer::addFieldItem(QString field) +{ + cmbFields->insertItem(field); +} + +void QgsDlgPgBuffer::addSchema(QString schema) +{ + cmbSchema->insertItem(schema); +} + +void QgsDlgPgBuffer::setSrid(QString srid) +{ + txtSrid->setText(srid); +} + +void QgsDlgPgBuffer::setBufferLayerName(QString name) +{ + txtBufferedLayerName->setText(name); +} + +void QgsDlgPgBuffer::setGeometryColumn(QString name) +{ + txtGeometryColumn->setText(name); +} diff --git a/plugins/geoprocessing/qgsdlgpgbuffer.h b/plugins/geoprocessing/qgsdlgpgbuffer.h index e9244ebce35..6a090fac142 100644 --- a/plugins/geoprocessing/qgsdlgpgbuffer.h +++ b/plugins/geoprocessing/qgsdlgpgbuffer.h @@ -1,24 +1,58 @@ +/*************************************************************************** + qgsdlgbuffer.h + Buffer dialog - Subclasses qgsdlgbufferbase + Part of the Geoprocessing plugin for PostgreSQL/PostGIS layers + ------------------- + begin : Jan 21, 2004 + copyright : (C) 2004 by Gary E.Sherman + email : sherman at mrcc.com + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + /* $Id$ */ #ifndef QGSDLGPGBUFFER_H #define QGSDLGPGBUFFER_H #include "qgsdlgpgbufferbase.h" -class QgsDlgPgBuffer : public QgsDlgPgBufferBase +class QgsDlgPgBuffer:public QgsDlgPgBufferBase { - Q_OBJECT -public: - QgsDlgPgBuffer(QWidget *parent=0, const char *name=0); - QgsDlgPgBuffer::~QgsDlgPgBuffer(); - void setBufferLabel(QString &lbl); - QString bufferDistance(); - QString bufferLayerName(); - QString objectIdColumn(); - QString geometryColumn(); - QString srid(); - QString schema(); - bool addLayerToMap(); - void addFieldItem(QString field); - void addSchema(QString schema); - void setSrid(QString srid); - void setBufferLayerName(QString name); - void setGeometryColumn(QString name); - }; + Q_OBJECT public: + //! Constructor + QgsDlgPgBuffer(QWidget * parent = 0, const char *name = 0); + //! Destructor + QgsDlgPgBuffer::~QgsDlgPgBuffer(); + //! Set the information label in the dialog + void setBufferLabel(QString & lbl); + //! Get the buffer distance + QString bufferDistance(); + //! Get the name of the buffered layer to be created + QString bufferLayerName(); + //! Get the name of the column to be used as the object id (unique key) + QString objectIdColumn(); + //! Get the name to use for the geometry column in the buffered layer + QString geometryColumn(); + //! Get the srid to use when creating the buffered layer + QString srid(); + //! Get the schema name for the new layer + QString schema(); + //! Flag to indicate if the layer should be added to the map + bool addLayerToMap(); + //! Add a field name to the list of fields available for use as the object id + void addFieldItem(QString field); + //! Add a schema name to the list of available schemas + void addSchema(QString schema); + //! Set the srid value on the dialog + void setSrid(QString srid); + //! Set the bufferd layer name on the dialog + void setBufferLayerName(QString name); + //! Set the geometry column on the dialog + void setGeometryColumn(QString name); +}; #endif // QGSDLGPGBUFFER_H diff --git a/plugins/geoprocessing/qgspggeoprocessing.cpp b/plugins/geoprocessing/qgspggeoprocessing.cpp index 2dfc4483e7a..f445d4e89cb 100644 --- a/plugins/geoprocessing/qgspggeoprocessing.cpp +++ b/plugins/geoprocessing/qgspggeoprocessing.cpp @@ -117,7 +117,7 @@ void QgsPgGeoprocessing::buffer() // create the connection string QString connInfo = dataSource.left(dataSource.find("table=")); - QMessageBox::information(0, "Data source", QString("Datasource:%1\n\nConnectionInfo:%2").arg(dataSource).arg(connInfo)); + std::cerr << "Data source = " << QString("Datasource:%1\n\nConnectionInfo:%2").arg(dataSource).arg(connInfo) << std::endl; // get the table name QStringList connStrings = QStringList::split(" ", dataSource); QStringList tables = connStrings.grep("table="); @@ -133,113 +133,162 @@ void QgsPgGeoprocessing::buffer() QStringList userNames = connStrings.grep("user="); QString user = userNames[0]; user = user.mid(user.find("=") + 1); - + // show dialog to fetch buffer distrance, new layer name, and option to QgsDlgPgBuffer *bb = new QgsDlgPgBuffer(); // set the label QString lbl = tr("Buffer features in layer %1").arg(tableName); bb->setBufferLabel(lbl); // set a default output table name - bb->setBufferLayerName(tableName.mid(tableName.find(".")+1) + "_buffer"); + bb->setBufferLayerName(tableName.mid(tableName.find(".") + 1) + "_buffer"); // set the fields on the dialog box drop-down QgsDataProvider *dp = lyr->getDataProvider(); - std::vector flds = dp->fields(); - for(int i=0; i < flds.size(); i++){ - // check the field type -- if its int we can use it - if(flds[i].getType().find("int") > -1){ - bb->addFieldItem(flds[i].getName()); - } + std::vector < QgsField > flds = dp->fields(); + for (int i = 0; i < flds.size(); i++) { + // check the field type -- if its int we can use it + if (flds[i].getType().find("int") > -1) { + bb->addFieldItem(flds[i].getName()); + } } - // connect to the database - PGconn *conn = PQconnectdb((const char *) connInfo); - if (PQstatus(conn) == CONNECTION_OK) { - // populate the schema drop-down - QString schemaSql = QString("select nspname from pg_namespace,pg_user where nspowner = usesysid and usename = '%1'").arg(user); - PGresult *schemas = PQexec(conn, (const char *) schemaSql); - if(PQresultStatus(schemas) == PGRES_TUPLES_OK){ - // add the schemas to the drop-down, otherwise just public (the - // default) will show up - for(int i=0; i < PQntuples(schemas); i++){ - bb->addSchema(PQgetvalue(schemas,i,0)); - } - } - PQclear(schemas); - // query the geometry_columns table to get the srid and use it as default - QString sridSql = QString("select srid,f_geometry_column from geometry_columns where f_table_schema='%1' and f_table_name='%2'") - .arg(schema) - .arg(tableName.mid(tableName.find(".")+1)); - QMessageBox::information(0,"SRID SQL",sridSql); - QString geometryCol; - PGresult *sridq = PQexec(conn,(const char *)sridSql); - if(PQresultStatus(sridq) == PGRES_TUPLES_OK){ - bb->setSrid(PQgetvalue(sridq,0,0)); - geometryCol = PQgetvalue(sridq,0,1); - bb->setGeometryColumn(geometryCol); - }else{ - bb->setSrid("-1"); - } - PQclear(sridq); - // exec the dialog and process if user selects ok - if (bb->exec()) { + // connect to the database + PGconn *conn = PQconnectdb((const char *) connInfo); + if (PQstatus(conn) == CONNECTION_OK) { + // populate the schema drop-down + QString schemaSql = + QString("select nspname from pg_namespace,pg_user where nspowner = usesysid and usename = '%1'").arg(user); + PGresult *schemas = PQexec(conn, (const char *) schemaSql); + if (PQresultStatus(schemas) == PGRES_TUPLES_OK) { + // add the schemas to the drop-down, otherwise just public (the + // default) will show up + for (int i = 0; i < PQntuples(schemas); i++) { + bb->addSchema(PQgetvalue(schemas, i, 0)); + } + } + PQclear(schemas); + // query the geometry_columns table to get the srid and use it as default + QString sridSql = + QString("select srid,f_geometry_column from geometry_columns where f_table_schema='%1' and f_table_name='%2'") + .arg(schema) + .arg(tableName.mid(tableName.find(".") + 1)); + std::cerr << "SRID SQL" << sridSql << std::endl; + QString geometryCol; + PGresult *sridq = PQexec(conn, (const char *) sridSql); + if (PQresultStatus(sridq) == PGRES_TUPLES_OK) { + bb->setSrid(PQgetvalue(sridq, 0, 0)); + geometryCol = PQgetvalue(sridq, 0, 1); + bb->setGeometryColumn(geometryCol); + } else { + bb->setSrid("-1"); + } + PQclear(sridq); + // exec the dialog and process if user selects ok + if (bb->exec()) { // determine what column to use as the obj id QString objId = bb->objectIdColumn(); QString objIdType = "int"; QString objIdValue; - if(objId == "Create unique object id"){ - objId = "objectid"; - objIdType = "serial"; - objIdValue = "0"; - }else{ - objIdValue = objId; + if (objId == "Create unique object id") { + objId = "objectid"; + objIdType = "serial"; + objIdValue = "DEFAULT"; + } else { + objIdValue = objId; } + // set the schema path (need public to find the postgis + // functions) + PGresult *result = PQexec(conn, "begin work"); + PQclear(result); + QString sql = QString("set search_path = '%1','public'").arg(bb->schema()); + result = PQexec(conn, (const char *) sql); + PQclear(result); + std::cerr << sql << std::endl; // first create the new table - - QString sql = QString("create table %1.%2 (%3 %4)") + + sql = QString("create table %1.%2 (%3 %4)") .arg(bb->schema()) .arg(bb->bufferLayerName()) .arg(objId) .arg(objIdType); - - PGresult *result = PQexec(conn, (const char *) sql); + std::cerr << sql << std::endl; + result = PQexec(conn, (const char *) sql); + std::cerr << "Status from create table is " << PQresultStatus(result) << std::endl; if (PQresultStatus(result) == PGRES_COMMAND_OK) { + PQclear(result); // add the geometry column //, , , , , - sql = QString("select addgeometrycolumn('%1','%2.%4','%4',%5,'%6',%7)") + sql = QString("select addgeometrycolumn('%1','%2','%3',%4,'%5',%6)") .arg(dbname) - .arg(bb->schema()) .arg(bb->bufferLayerName()) .arg(bb->geometryColumn()) .arg(bb->srid()) .arg("POLYGON") .arg("2"); - QMessageBox::information(0,"AddGeomCol",sql); - PGresult *geoCol = PQexec(conn, (const char *)sql); - if(PQresultStatus(geoCol) == PGRES_COMMAND_OK) { - // do the buffer and insert the features + std::cerr << sql << std::endl; + PGresult *geoCol = PQexec(conn, (const char *) sql); + PQclear(geoCol); + // drop the check constraint based on geometry type + sql = QString("alter table %1.%2 drop constraint \"$2\"") + .arg(bb->schema()) + .arg(bb->bufferLayerName()); + std::cerr << sql << std::endl; + result = PQexec(conn, (const char *) sql); + PQclear(result); + // if(PQresultStatus(geoCol) == PGRES_COMMAND_OK) { + // do the buffer and insert the features + if (objId == "objectid") { + sql = QString("insert into %1 (%2) select buffer(%3,%4) from %5") + .arg(bb->bufferLayerName()) + .arg(bb->geometryColumn()) + .arg(geometryCol) + .arg(bb->bufferDistance().toDouble()) + .arg(tableName); + } else { sql = QString("insert into %1 select %2, buffer(%3,%4) from %5") .arg(bb->bufferLayerName()) .arg(objIdValue) .arg(geometryCol) .arg(bb->bufferDistance().toDouble()) .arg(tableName); - PQexec(conn, (const char *)sql); - } - // add new layer to the map - if(bb->addLayerToMap()){ - // create the connection string - QString conn = "dbname=%1 host"; - } + std::cerr << sql << std::endl; + + } + result = PQexec(conn, (const char *) sql); + PQclear(result); + // } + std::cerr << sql << std::endl; + result = PQexec(conn, "end work"); + PQclear(result); + result = PQexec(conn, "commit;vacuum"); + PQclear(result); + PQfinish(conn); + QMessageBox::information(0, "Add to Map?", "Do you want to add the layer to the map?"); + // add new layer to the map + if (bb->addLayerToMap()) { + // create the connection string + QString newLayerSource = dataSource.left(dataSource.find("table=")); + std::cerr << "newLayerSource: " << newLayerSource << std::endl; + // add the schema.table and geometry column + /* newLayerSource += "table=" + bb->schema() + "." + bb->bufferLayerName() + + " (" + bb->geometryColumn() + ")"; */ + std::cerr << "newLayerSource: " << newLayerSource << std::endl; + std::cerr << "Adding new layer using\n\t" << newLayerSource << std::endl; + // host=localhost dbname=gis_data user=gsherman password= table=public.alaska (the_geom) + qI->addVectorLayer(newLayerSource, bb->schema() + "." + bb->bufferLayerName() + + " (" + bb->geometryColumn() + ")", "postgres"); + + } } else { QMessageBox::critical(0, "Unable to create table", QString("Failed to create the output table %1").arg(bb->bufferLayerName())); } - - } - } else { - // connection error - QString err = tr("Error connecting to the database"); - QMessageBox::critical(0, err, PQerrorMessage(conn)); + } + delete bb; + } else { + // connection error + QString err = tr("Error connecting to the database"); + QMessageBox::critical(0, err, PQerrorMessage(conn)); + } } else { QMessageBox::critical(0, "Not a PostgreSQL/PosGIS Layer", QString diff --git a/plugins/geoprocessing/qgspggeoprocessing.h b/plugins/geoprocessing/qgspggeoprocessing.h index 0d79d9be7e4..32566e052d4 100644 --- a/plugins/geoprocessing/qgspggeoprocessing.h +++ b/plugins/geoprocessing/qgspggeoprocessing.h @@ -37,61 +37,61 @@ class QPopupMenu; * \brief PostgreSQL/PostGIS plugin for QGIS * */ -class QgsPgGeoprocessing : public QObject, public QgisPlugin{ -Q_OBJECT -public: +class QgsPgGeoprocessing:public QObject, public QgisPlugin +{ + Q_OBJECT public: /** * Constructor for a plugin. The QgisApp and QgisIface pointers are passed by * QGIS when it attempts to instantiate the plugin. * @param qgis Pointer to the QgisApp object * @param qI Pointer to the QgisIface object. */ - QgsPgGeoprocessing(QgisApp *qgis, QgisIface *qI); - /** + QgsPgGeoprocessing(QgisApp * qgis, QgisIface * qI); + /** * Virtual function to return the name of the plugin. The name will be used when presenting a list * of installable plugins to the user */ - virtual QString name(); - /** + virtual QString name(); + /** * Virtual function to return the version of the plugin. */ - virtual QString version(); - /** + virtual QString version(); + /** * Virtual function to return a description of the plugins functions */ - virtual QString description(); - /** + virtual QString description(); + /** * Return the plugin type */ - virtual int type(); - //! init the gui - virtual void initGui(); - //! Destructor - virtual ~QgsPgGeoprocessing(); -public slots: - //! buffer features in a layer - void buffer(); - //! unload the plugin - void unload(); -private: + virtual int type(); + //! init the gui + virtual void initGui(); + //! Destructor + virtual ~ QgsPgGeoprocessing(); + public slots: + //! buffer features in a layer + void buffer(); + //! unload the plugin + void unload(); + private: //! Name of the plugin - QString pName; - //! Version - QString pVersion; - //! Descrption of the plugin - QString pDescription; - //! Plugin type as defined in QgisPlugin::PLUGINTYPE - int ptype; - //! Id of the plugin's menu. Used for unloading - int menuId; - //! Pointer to our toolbar - QToolBar *toolBar; - //! Pointer to our menu - QMenuBar *menu; - //! Pionter to QGIS main application object - QgisApp *qgisMainWindow; - //! Pointer to the QGIS interface object - QgisIface *qI; + QString pName; + //! Version + QString pVersion; + //! Descrption of the plugin + QString pDescription; + //! Plugin type as defined in QgisPlugin::PLUGINTYPE + int ptype; + //! Id of the plugin's menu. Used for unloading + int menuId; + //! Pointer to our toolbar + QToolBar *toolBar; + //! Pointer to our menu + QMenuBar *menu; + //! Pionter to QGIS main application object + QgisApp *qgisMainWindow; + //! Pointer to the QGIS interface object + QgisIface *qI; }; #endif