PostGIS layer selection:

- actually do the geometry type lookup threaded
- combobox removed and replaced with multiple rows, one each geometry type
- add wait cursors while looking up tables and inserting layers



git-svn-id: http://svn.osgeo.org/qgis/trunk@7627 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
jef 2007-11-20 22:29:43 +00:00
parent 6cc8071535
commit dd475e221e
3 changed files with 112 additions and 129 deletions

View File

@ -2071,9 +2071,11 @@ void QgisApp::addDatabaseLayer()
// add files to the map canvas // add files to the map canvas
QStringList tables = dbs->selectedTables(); QStringList tables = dbs->selectedTables();
QApplication::setOverrideCursor(Qt::waitCursor);
QString connInfo = dbs->connInfo(); QString connInfo = dbs->connInfo();
// for each selected table, connect to the database, parse the WKT geometry, // for each selected table, connect to the database, parse the WKT geometry,
// and build a cavnasitem for it // and build a canvasitem for it
// readWKB(connInfo,tables); // readWKB(connInfo,tables);
QStringList::Iterator it = tables.begin(); QStringList::Iterator it = tables.begin();
while (it != tables.end()) while (it != tables.end())
@ -2086,7 +2088,6 @@ void QgisApp::addDatabaseLayer()
{ {
// register this layer with the central layers registry // register this layer with the central layers registry
QgsMapLayerRegistry::instance()->addMapLayer(layer); QgsMapLayerRegistry::instance()->addMapLayer(layer);
} }
else else
{ {
@ -2097,6 +2098,9 @@ void QgisApp::addDatabaseLayer()
//qWarning("incrementing iterator"); //qWarning("incrementing iterator");
++it; ++it;
} }
QApplication::restoreOverrideCursor();
statusBar()->message(mMapCanvas->extent().stringRep(2)); statusBar()->message(mMapCanvas->extent().stringRep(2));
} }

View File

@ -156,49 +156,6 @@ void QgsDbSourceSelect::on_cmbConnections_activated(int)
dbChanged(); dbChanged();
} }
void QgsDbSourceSelect::updateTypeInfo(int row, QString type)
{
QComboBox *cb = static_cast<QComboBox *>(lstTables->cellWidget(row,dbssType));
if(!cb)
{
QTableWidgetItem *item = lstTables->takeItem(row,dbssType);
delete item;
}
#if 0 // Qt 4.3
else
lstTables->removeCellWidget(row, dbssType);
#endif
if( type.contains(",") )
{
QStringList types = type.split(",");
cb = new QComboBox(lstTables);
for(int i=0; i<types.size(); i++) {
cb->addItem( mLayerIcons.value(types[i]).second, mLayerIcons.value(types[i]).first);
}
cb->setCurrentIndex(0);
cb->setToolTip( tr("select import type for multi type layer") );
#if 0 // Qt 4.3
cb->setMinimumContentsLength(mCbMinLength);
cb->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
#endif
lstTables->setCellWidget(row, dbssType, cb);
}
else
{
if (!mLayerIcons.contains(type))
type="UNKNOWN";
QTableWidgetItem *iconItem = new QTableWidgetItem();
iconItem->setIcon( mLayerIcons.value(type).second );
iconItem->setToolTip( mLayerIcons.value(type).first );
lstTables->setItem(row, dbssType, iconItem);
lstTables->setItem(row, dbssType, new QTableWidgetItem(*lstTables->item(row,dbssType)));
}
}
void QgsDbSourceSelect::setLayerType(QString schema, void QgsDbSourceSelect::setLayerType(QString schema,
QString table, QString column, QString table, QString column,
QString type) QString type)
@ -207,14 +164,31 @@ void QgsDbSourceSelect::setLayerType(QString schema,
// Find the right row in the table by searching for the text that // Find the right row in the table by searching for the text that
// was put into the Name column. // was put into the Name column.
QString full_desc = fullDescription(schema, table, column); QString full_desc = fullDescription(schema, table, column, "WAITING");
QList<QTableWidgetItem*> ii = lstTables->findItems(full_desc, Qt::MatchExactly); QList<QTableWidgetItem*> ii = lstTables->findItems(full_desc, Qt::MatchExactly);
if (ii.count() > 0) if (ii.count() > 0)
{ {
updateTypeInfo( lstTables->row(ii.at(0)), type); int row = lstTables->row(ii.at(0));
lstTables->resizeColumnToContents(dbssType);
if(type!="")
{
QStringList types = type.split(",");
updateRow(row, fullDescription(schema, table, column, "AS " + types[0]), types[0]);
for(int i=1; i<types.size(); i++) {
lstTables->insertRow(row+1);
initRow(row+1);
updateRow(row+1, fullDescription(schema, table, column, "AS " + types[i]), types[i]);
}
lstTables->resizeColumnsToContents();
}
else
{
lstTables->removeRow(row);
}
} }
} }
@ -249,7 +223,6 @@ void QgsDbSourceSelect::populateConnectionList()
} }
void QgsDbSourceSelect::addNewConnection() void QgsDbSourceSelect::addNewConnection()
{ {
QgsNewConnection *nc = new QgsNewConnection(this); QgsNewConnection *nc = new QgsNewConnection(this);
if (nc->exec()) if (nc->exec())
@ -295,31 +268,21 @@ void QgsDbSourceSelect::addTables()
{ {
//store the table info //store the table info
for (int i = 0; i < lstTables->rowCount();) for (int i=0; i<lstTables->rowCount(); i++)
{ {
if ( lstTables->isItemSelected(lstTables->item(i, dbssDetail)) ) if ( lstTables->isItemSelected(lstTables->item(i, dbssDetail)) )
{ {
QString table = lstTables->item(i,dbssDetail)->text(); QString table = lstTables->item(i,dbssDetail)->text();
QString query = table + " sql="; QString query;
QComboBox *cb = static_cast<QComboBox *>( lstTables->cellWidget(i, dbssType) ); bool applyFilter = table.contains(") AS ");
if(cb) if( applyFilter ) {
{
int i = table.find("("); int i = table.find("(");
int j = table.find(")"); int j = table.find(")");
QString column = table.mid(i+1,j-i-1); QString column = table.mid(i+1,j-i-1);
QString type; QString type = table.mid(j+5);
query += table.left(j+1) + " sql=";
QMapIterator <QString, QPair < QString, QIcon > > it(mLayerIcons);
while( it.hasNext() ) {
it.next();
if( it.value().first == cb->currentText() ) {
type=it.key();
break;
}
}
if( type=="POINT" ) { if( type=="POINT" ) {
query += QString("GeometryType(\"%1\") IN ('POINT','MULTIPOINT')").arg(column); query += QString("GeometryType(\"%1\") IN ('POINT','MULTIPOINT')").arg(column);
} else if(type=="LINESTRING") { } else if(type=="LINESTRING") {
@ -330,11 +293,15 @@ void QgsDbSourceSelect::addTables()
continue; continue;
} }
} }
else
{
query += table + " sql=";
}
QTableWidgetItem *sqlItem = lstTables->item(i, dbssSql); QTableWidgetItem *sqlItem = lstTables->item(i, dbssSql);
if (sqlItem && sqlItem->text()!="" ) if (sqlItem && sqlItem->text()!="" )
{ {
if(cb) if(applyFilter)
query += QString(" AND (%1)").arg( sqlItem->text() ); query += QString(" AND (%1)").arg( sqlItem->text() );
else else
query += sqlItem->text(); query += sqlItem->text();
@ -342,19 +309,45 @@ void QgsDbSourceSelect::addTables()
m_selectedTables += query; m_selectedTables += query;
} }
i++;
} }
// BEGIN CHANGES ECOS // BEGIN CHANGES ECOS
if (m_selectedTables.empty() == true) if ( m_selectedTables.empty() )
QMessageBox::information(this, tr("Select Table"), tr("You must select a table in order to add a Layer.")); QMessageBox::information(this, tr("Select Table"), tr("You must select a table in order to add a Layer."));
else else
accept(); accept();
// END CHANGES ECOS // END CHANGES ECOS
} }
void QgsDbSourceSelect::initRow(int row)
{
QTableWidgetItem *iconItem = new QTableWidgetItem();
lstTables->setItem(row, dbssType, iconItem);
QTableWidgetItem *textItem = new QTableWidgetItem();
textItem->setToolTip( tr("double click to open PostgreSQL query builder") );
lstTables->setItem(row, dbssDetail, textItem);
}
void QgsDbSourceSelect::updateRow(int row, QString detail, QString type)
{
if (!mLayerIcons.contains(type))
type="UNKNOWN";
QTableWidgetItem *iconItem = lstTables->item(row, dbssType);
iconItem->setIcon( mLayerIcons.value(type).second );
iconItem->setToolTip( mLayerIcons.value(type).first );
lstTables->item(row, dbssDetail)->setText( detail );
}
void QgsDbSourceSelect::on_btnConnect_clicked() void QgsDbSourceSelect::on_btnConnect_clicked()
{ {
if(mColumnTypeThread)
{
mColumnTypeThread->stop();
mColumnTypeThread=0;
}
// populate the table list // populate the table list
QSettings settings; QSettings settings;
@ -445,16 +438,6 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
mLayerIcons.insert("UNKNOWN", mLayerIcons.insert("UNKNOWN",
qMakePair(tr("Unknown layer type"), qMakePair(tr("Unknown layer type"),
QIcon(myThemePath+"/mIconUnknownLayerType.png"))); QIcon(myThemePath+"/mIconUnknownLayerType.png")));
#if 0 // Qt 4.3
mCbMinLength = 0;
QMapIterator <QString, QPair < QString, QIcon > > it(mLayerIcons);
while( it.hasNext() ) {
it.next();
int len = it.value().first.length();;
mCbMinLength = mCbMinLength<len ? len : mCbMinLength;
}
#endif
} }
//qDebug("Connection succeeded"); //qDebug("Connection succeeded");
// tell the DB that we want text encoded in UTF8 // tell the DB that we want text encoded in UTF8
@ -476,14 +459,12 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
geomCol::const_iterator iter = details.begin(); geomCol::const_iterator iter = details.begin();
for (; iter != details.end(); ++iter) for (; iter != details.end(); ++iter)
{ {
QString type = iter->second;
int row = lstTables->rowCount(); int row = lstTables->rowCount();
lstTables->setRowCount(row+1); lstTables->setRowCount(row+1);
QTableWidgetItem *textItem = new QTableWidgetItem(iter->first); initRow(row);
textItem->setToolTip( tr("double click to open PostgreSQL query builder") ); updateRow(row, iter->first, type);
lstTables->setItem(row, dbssDetail, textItem);
updateTypeInfo(row, iter->second);
} }
// And tidy up the columns & rows // And tidy up the columns & rows
@ -494,19 +475,13 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
// may take a long time to return // may take a long time to return
if (mColumnTypeThread != NULL) if (mColumnTypeThread != NULL)
{ {
connect(mColumnTypeThread, connect(mColumnTypeThread, SIGNAL(setLayerType(QString,QString,QString,QString)),
SIGNAL(setLayerType(QString,QString,QString,QString)), this, SLOT(setLayerType(QString,QString,QString,QString)));
this, connect(this, SIGNAL(finished()),
SLOT(setLayerType(QString,QString,QString,QString))); mColumnTypeThread, SLOT(stop()) );
// Do it in a thread. Does not yet cope correctly with the
// layer selection dialog box closing before the thread
// completes, nor the qgis process ending before the
// thread completes, nor does the thread know to stop working
// when the user chooses a layer.
//mColumnTypeThread->start();
// do it in this process for the moment. // Do it in a thread.
mColumnTypeThread->getLayerTypes(); mColumnTypeThread->start();
} }
} }
else else
@ -590,6 +565,8 @@ bool QgsDbSourceSelect::getGeometryColumnInfo(PGconn *pg,
{ {
bool ok = false; bool ok = false;
QApplication::setOverrideCursor(Qt::waitCursor);
QString sql = "select * from geometry_columns"; QString sql = "select * from geometry_columns";
// where f_table_schema ='" + settings.readEntry(key + "/database") + "'"; // where f_table_schema ='" + settings.readEntry(key + "/database") + "'";
sql += " order by f_table_schema,f_table_name"; sql += " order by f_table_schema,f_table_name";
@ -620,28 +597,14 @@ bool QgsDbSourceSelect::getGeometryColumnInfo(PGconn *pg,
{ {
QString column = PQgetvalue(result, idx, PQfnumber(result, "f_geometry_column")); QString column = PQgetvalue(result, idx, PQfnumber(result, "f_geometry_column"));
QString type = PQgetvalue(result, idx, PQfnumber(result, "type")); QString type = PQgetvalue(result, idx, PQfnumber(result, "type"));
QString v = "";
if (schemaName.length() > 0)
{
v += '"';
v += schemaName;
v += "\".";
}
v += '"';
v += tableName;
v += "\" (";
v += column;
v += ")";
QString as = "";
if(type=="GEOMETRY" && !searchGeometryColumnsOnly) { if(type=="GEOMETRY" && !searchGeometryColumnsOnly) {
addSearchGeometryColumn(schemaName, tableName, column); addSearchGeometryColumn(schemaName, tableName, column);
type="WAITING"; as=type="WAITING";
} }
details.push_back(geomPair(v, type)); details.push_back(geomPair(fullDescription(schemaName, tableName, column, as), type));
} }
PQclear(exists); PQclear(exists);
} }
@ -649,6 +612,8 @@ bool QgsDbSourceSelect::getGeometryColumnInfo(PGconn *pg,
} }
PQclear(result); PQclear(result);
QApplication::restoreOverrideCursor();
if (searchGeometryColumnsOnly) if (searchGeometryColumnsOnly)
return ok; return ok;
@ -685,11 +650,8 @@ bool QgsDbSourceSelect::getGeometryColumnInfo(PGconn *pg,
QString column = PQgetvalue(result, i, 2); // attname QString column = PQgetvalue(result, i, 2); // attname
QString relkind = PQgetvalue(result, i, 3); // relation kind QString relkind = PQgetvalue(result, i, 3); // relation kind
QString full_desc = fullDescription(schema, table, column);
addSearchGeometryColumn(schema, table, column); addSearchGeometryColumn(schema, table, column);
details.push_back(geomPair(fullDescription(schema, table, column, "WAITING"), "WAITING"));
details.push_back(geomPair(full_desc, "WAITING"));
} }
ok = true; ok = true;
@ -706,12 +668,12 @@ void QgsDbSourceSelect::showHelp()
QgsContextHelp::run(context_id); QgsContextHelp::run(context_id);
} }
QString QgsDbSourceSelect::fullDescription(QString schema, QString table, QString QgsDbSourceSelect::fullDescription(QString schema, QString table,
QString column) QString column, QString type)
{ {
QString full_desc = ""; QString full_desc = "";
if (schema.length() > 0) if (schema.length() > 0)
full_desc = '"' + schema + "\".\""; full_desc = '"' + schema + "\".\"";
full_desc += table + "\" (" + column + ")"; full_desc += table + "\" (" + column + ") " + type;
return full_desc; return full_desc;
} }
void QgsDbSourceSelect::dbChanged() void QgsDbSourceSelect::dbChanged()
@ -765,19 +727,25 @@ void QgsGeomColumnTypeThread::addGeometryColumn(QString schema, QString table, Q
columns.push_back(column); columns.push_back(column);
} }
void QgsGeomColumnTypeThread::stop()
{
mStopped=true;
}
void QgsGeomColumnTypeThread::getLayerTypes() void QgsGeomColumnTypeThread::getLayerTypes()
{ {
mStopped=false;
PGconn *pd = PQconnectdb(mConnInfo.toLocal8Bit().data()); PGconn *pd = PQconnectdb(mConnInfo.toLocal8Bit().data());
if (PQstatus(pd) == CONNECTION_OK) if (PQstatus(pd) == CONNECTION_OK)
{ {
PQsetClientEncoding(pd, "UNICODE"); PQsetClientEncoding(pd, "UNICODE");
for (uint i = 0; i < schemas.size(); ++i) for (uint i = 0; i<schemas.size(); i++)
{ {
QString query = QgsDbSourceSelect::makeGeomQuery(schemas[i], QString query = QgsDbSourceSelect::makeGeomQuery(schemas[i],
tables[i], tables[i],
columns[i]); columns[i]);
QgsDebugMsg("Running SQL:" + query);
PGresult* gresult = PQexec(pd, query.toLocal8Bit().data()); PGresult* gresult = PQexec(pd, query.toLocal8Bit().data());
QString type; QString type;
if (PQresultStatus(gresult) == PGRES_TUPLES_OK) { if (PQresultStatus(gresult) == PGRES_TUPLES_OK) {
@ -785,13 +753,17 @@ void QgsGeomColumnTypeThread::getLayerTypes()
for(int j=0; j<PQntuples(gresult); j++) { for(int j=0; j<PQntuples(gresult); j++) {
QString type = PQgetvalue(gresult, j, 0); QString type = PQgetvalue(gresult, j, 0);
types += type!="" ? type : "UNKNOWN"; if(type!="")
types += type;
} }
type = types.join(","); type = types.join(",");
} }
PQclear(gresult); PQclear(gresult);
if(mStopped)
break;
// Now tell the layer list dialog box... // Now tell the layer list dialog box...
emit setLayerType(schemas[i], tables[i], columns[i], type); emit setLayerType(schemas[i], tables[i], columns[i], type);
} }

View File

@ -42,12 +42,12 @@ class QgisApp;
* \brief Dialog to create connections and add tables from PostgresQL. * \brief Dialog to create connections and add tables from PostgresQL.
* *
* This dialog allows the user to define and save connection information * This dialog allows the user to define and save connection information
* for PostGIS enabled PostgresQL databases. The user can then connect and add * for PostGIS enabled PostgreSQL databases. The user can then connect and add
* tables from the database to the map canvas. * tables from the database to the map canvas.
*/ */
class QgsDbSourceSelect : public QDialog, private Ui::QgsDbSourceSelectBase class QgsDbSourceSelect : public QDialog, private Ui::QgsDbSourceSelectBase
{ {
Q_OBJECT Q_OBJECT
public: public:
//! Constructor //! Constructor
@ -76,7 +76,7 @@ class QgsDbSourceSelect : public QDialog, private Ui::QgsDbSourceSelectBase
// geometry type of a column // geometry type of a column
static QString makeGeomQuery(QString schema, QString table, QString column); static QString makeGeomQuery(QString schema, QString table, QString column);
public slots: public slots:
/*! Connects to the database using the stored connection parameters. /*! Connects to the database using the stored connection parameters.
* Once connected, available layers are displayed. * Once connected, available layers are displayed.
*/ */
@ -115,11 +115,13 @@ class QgsDbSourceSelect : public QDialog, private Ui::QgsDbSourceSelectBase
void setConnectionListPosition(); void setConnectionListPosition();
// Show the context help for the dialog // Show the context help for the dialog
void showHelp(); void showHelp();
// update type column // initialize row
void updateTypeInfo(int row, QString type); void initRow(int row);
// update the row
void updateRow(int row, QString detail, QString type);
// Combine the schema, table and column data into a single string // Combine the schema, table and column data into a single string
// useful for display to the user // useful for display to the user
QString fullDescription(QString schema, QString table, QString column); QString fullDescription(QString schema, QString table, QString column, QString type);
// The column labels // The column labels
QStringList mColumnLabels; QStringList mColumnLabels;
// Our thread for doing long running queries // Our thread for doing long running queries
@ -161,12 +163,17 @@ class QgsGeomColumnTypeThread : public QThread
virtual void run() { getLayerTypes(); } virtual void run() { getLayerTypes(); }
void getLayerTypes(); void getLayerTypes();
signals: signals:
void setLayerType(QString schema, QString table, QString column, void setLayerType(QString schema, QString table, QString column,
QString type); QString type);
public slots:
void stop();
private: private:
QString mConnInfo; QString mConnInfo;
bool mStopped;
std::vector<QString> schemas, tables, columns; std::vector<QString> schemas, tables, columns;
}; };