Skip to content

Commit 25470f2

Browse files
author
g_j_m
committed
Further progress on dealing with slowness in populating the database
layer selection dialog box. Changes to code for selecting layer type icon git-svn-id: http://svn.osgeo.org/qgis/trunk@5040 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent b22661e commit 25470f2

File tree

2 files changed

+216
-68
lines changed

2 files changed

+216
-68
lines changed

src/gui/qgsdbsourceselect.cpp

+165-67
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,13 @@ email : sherman at mrcc.com
3030
#include <QSettings>
3131
#include <QTextOStream>
3232
#include <QTableWidgetItem>
33-
#include <QIcon>
3433
#include <QHeaderView>
3534

3635
#include <cassert>
3736
#include <iostream>
3837

3938
QgsDbSourceSelect::QgsDbSourceSelect(QgisApp *app, Qt::WFlags fl)
40-
: QDialog(app, fl), qgisApp(app)
39+
: QDialog(app, fl), qgisApp(app), mColumnTypeThread(NULL)
4140
{
4241
setupUi(this);
4342
btnAdd->setEnabled(false);
@@ -105,9 +104,9 @@ QgsDbSourceSelect::QgsDbSourceSelect(QgisApp *app, Qt::WFlags fl)
105104

106105
// Do some things that couldn't be done in designer
107106
lstTables->horizontalHeader()->setStretchLastSection(true);
107+
QStringList labels;
108108
// Set the column count to 3 for the type, name, and sql
109109
lstTables->setColumnCount(3);
110-
QStringList labels;
111110
labels += tr("Type"); labels += tr("Name"); labels += tr("Sql");
112111
lstTables->setHorizontalHeaderLabels(labels);
113112
lstTables->verticalHeader()->hide();
@@ -148,6 +147,59 @@ void QgsDbSourceSelect::on_btnHelp_clicked()
148147
}
149148
/** End Autoconnected SLOTS **/
150149

150+
void QgsDbSourceSelect::setLayerType(QString schema,
151+
QString table, QString column,
152+
QString type)
153+
{
154+
#ifdef QGISDEBUG
155+
std::cerr << "Received layer type of " << type.toLocal8Bit().data()
156+
<< " for "
157+
<< (schema+'.'+table+'.'+column).toLocal8Bit().data()
158+
<< '\n';
159+
#endif
160+
161+
// Find the right row in the table by searching for the text that
162+
// was put into the Name column.
163+
QString full_desc = fullDescription(schema, table, column);
164+
165+
QList<QTableWidgetItem*> ii = lstTables->findItems(full_desc,
166+
Qt::MatchExactly);
167+
168+
if (ii.count() > 0)
169+
{
170+
int row = lstTables->row(ii.at(0)); // just use the first one
171+
QTableWidgetItem* iconItem = lstTables->item(row, 0);
172+
173+
// Get the icon and tooltip text
174+
const QIcon* p;
175+
QString toolTipText;
176+
if (mLayerIcons.contains(type))
177+
{
178+
p = &(mLayerIcons.value(type).second);
179+
toolTipText = mLayerIcons.value(type).first;
180+
}
181+
else
182+
{
183+
qDebug(("Unknown geometry type of " + type).toLocal8Bit().data());
184+
p = &(mLayerIcons.value("UNKNOWN").second);
185+
toolTipText = mLayerIcons.value("UNKNOWN").first;
186+
}
187+
188+
iconItem->setIcon(*p);
189+
iconItem->setToolTip(toolTipText);
190+
}
191+
}
192+
193+
QString QgsDbSourceSelect::makeGeomQuery(QString schema,
194+
QString table, QString column)
195+
{
196+
QString query = "select GeometryType(" + column + ") from ";
197+
if (schema.length() > 0)
198+
query += "\"" + schema + "\".";
199+
query += "\"" + table + "\" where " + column + " is not null limit 1";
200+
return query;
201+
}
202+
151203
QgsDbSourceSelect::~QgsDbSourceSelect()
152204
{
153205
PQfinish(pd);
@@ -278,13 +330,31 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
278330
{
279331
// create the pixmaps for the layer types
280332
QString myThemePath = QgsApplication::themePath();
281-
QIcon pxPoint(myThemePath+"/mIconPointLayer.png");
282-
QIcon pxLine(myThemePath+"/mIconLineLayer.png");
283-
QIcon pxPoly(myThemePath+"/mIconPolygonLayer.png");
284-
QIcon pxWaiting(myThemePath+"/mIconWaitingForLayerType.png");
285-
QIcon pxUnknown(myThemePath+"/mIconUnknownLayerType.png");
333+
mLayerIcons.insert(QString("POINT"),
334+
qMakePair(tr("Point layer"),
335+
QIcon(myThemePath+"/mIconPointLayer.png")));
336+
mLayerIcons.insert(QString("MULTIPOINT"),
337+
qMakePair(tr("Multi-point layer"),
338+
QIcon(myThemePath+"/mIconPointLayer.png")));
339+
mLayerIcons.insert(QString("LINESTRING"),
340+
qMakePair(tr("Linestring layer"),
341+
QIcon(myThemePath+"/mIconLineLayer.png")));
342+
mLayerIcons.insert(QString("MULTILINESTRING"),
343+
qMakePair(tr("Multi-linestring layer"),
344+
QIcon(myThemePath+"/mIconLineLayer.png")));
345+
mLayerIcons.insert(QString("POLYGON"),
346+
qMakePair(tr("Polygon layer"),
347+
QIcon(myThemePath+"/mIconPolygonLayer.png")));
348+
mLayerIcons.insert(QString("MULTIPOLYGON"),
349+
qMakePair(tr("Multi-polygon layer"),
350+
QIcon(myThemePath+"/mIconPolygonLayer.png")));
351+
mLayerIcons.insert(QString("WAITING"),
352+
qMakePair(tr("Waiting for layer type"),
353+
QIcon(myThemePath+"/mIconWaitingForLayerType.png")));
354+
mLayerIcons.insert(QString("UNKNOWN"),
355+
qMakePair(tr("Unknown layer type"),
356+
QIcon(myThemePath+"/mIconUnknownLayerType.png")));
286357

287-
assert (!pxPoint.isNull());
288358
//qDebug("Connection succeeded");
289359
// tell the DB that we want text encoded in UTF8
290360
PQsetClientEncoding(pd, "UNICODE");
@@ -299,47 +369,18 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
299369
for (; iter != details.end(); ++iter)
300370
{
301371
QString toolTipText;
302-
QIcon *p = 0;
303-
if (iter->second == "POINT")
304-
{
305-
p = &pxPoint;
306-
toolTipText = tr("Point layer");
307-
}
308-
else if (iter->second == "MULTIPOINT")
309-
{
310-
p = &pxPoint;
311-
toolTipText = tr("Multi-point layer");
312-
}
313-
else if (iter->second == "MULTIPOLYGON")
314-
{
315-
p = &pxPoly;
316-
toolTipText = tr("Multi-polygon layer");
317-
}
318-
else if (iter->second == "POLYGON")
319-
{
320-
p = &pxPoly;
321-
toolTipText = tr("Polygon layer");
322-
}
323-
else if (iter->second == "LINESTRING")
324-
{
325-
p = &pxLine;
326-
toolTipText = tr("Linestring layer");
327-
}
328-
else if (iter->second == "MULTILINESTRING")
329-
{
330-
p = &pxLine;
331-
toolTipText = tr("Multi-linestring layer");
332-
}
333-
else if (iter->second == "WAITING")
372+
const QIcon* p;
373+
374+
if (mLayerIcons.contains(iter->second))
334375
{
335-
p = &pxWaiting;
336-
toolTipText = tr("Waiting for layer type");
376+
p = &(mLayerIcons.value(iter->second).second);
377+
toolTipText = mLayerIcons.value(iter->second).first;
337378
}
338379
else
339380
{
340381
qDebug(("Unknown geometry type of " + iter->second).toLocal8Bit().data());
341-
toolTipText = tr("Unknown layer type");
342-
p = &pxUnknown;
382+
p = &(mLayerIcons.value("UNKNOWN").second);
383+
toolTipText = mLayerIcons.value("UNKNOWN").first;
343384
}
344385

345386
if (p != 0)
@@ -349,11 +390,6 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
349390
iconItem->setToolTip(toolTipText);
350391
QTableWidgetItem *textItem = new QTableWidgetItem(iter->first);
351392
int row = lstTables->rowCount();
352-
std::cerr << "Adding database table with name '"
353-
<< iter->first.toLocal8Bit().data()
354-
<< "' and tooltip '"
355-
<< toolTipText.toLocal8Bit().data()
356-
<< "' at row " << row+1 << ".\n";
357393
lstTables->setRowCount(row+1);
358394
lstTables->setItem(row, 0, iconItem);
359395
lstTables->setItem(row, 1, textItem);
@@ -370,6 +406,25 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
370406
// And tidy up the columns & rows
371407
lstTables->resizeColumnsToContents();
372408
lstTables->resizeRowsToContents();
409+
410+
// Start the thread that gets the geometry type for relations that
411+
// may take a long time to return
412+
if (mColumnTypeThread != NULL)
413+
{
414+
connect(mColumnTypeThread,
415+
SIGNAL(setLayerType(QString,QString,QString,QString)),
416+
this,
417+
SLOT(setLayerType(QString,QString,QString,QString)));
418+
// Do it in a thread. Does not yet cope correctly with the
419+
// layer selection dialog box closing before the thread
420+
// completes, nor the qgis process ending before the
421+
// thread completes, nor does the thread know to stop working
422+
// when the user chooses a layer.
423+
// mColumnTypeThread->run();
424+
425+
// do it in this process for the moment.
426+
mColumnTypeThread->getLayerTypes();
427+
}
373428
}
374429
else
375430
{
@@ -522,40 +577,35 @@ bool QgsDbSourceSelect::getGeometryColumnInfo(PGconn *pg,
522577
QString column = PQgetvalue(result, i, 2); // attname
523578
QString relkind = PQgetvalue(result, i, 3); // relation kind
524579

525-
QString type = "WAITING";
526-
if (relkind == "r" || relkind == "v")
527-
{
528-
QString query = "select GeometryType(" + column + ") from ";
529-
if (schema.length() > 0)
530-
query += "\"" + schema + "\".";
531-
query += "\"" + table + "\" where " + column + " is not null limit 1";
580+
QString full_desc = fullDescription(schema, table, column);
532581

582+
QString type = "UNKNOWN";
583+
if (relkind == "r")
584+
{
585+
QString query = makeGeomQuery(schema, table, column);
533586
PGresult* gresult = PQexec(pg, query.toLocal8Bit().data());
534587
if (PQresultStatus(gresult) != PGRES_TUPLES_OK)
535588
{
536589
QString myError = (tr("Access to relation ") + table + tr(" using sql;\n") + query +
537590
tr("\nhas failed. The database said:\n"));
538591
qDebug(myError + QString(PQresultErrorMessage(gresult)));
539-
type = "UNKNOWN";
540592
}
541593
else
542594
type = PQgetvalue(gresult, 0, 0); // GeometryType
543595
PQclear(gresult);
544596
}
545-
/*
546-
// Commented out temporarily...
547597
else // view
548598
{
549599
// store the column details and do the query in a thread
550-
std::cout << "Doing " << (schema+'.'+table+'.'+column).toLocal8Bit().data()
551-
<< " later" << std::endl;
600+
if (mColumnTypeThread == NULL)
601+
{
602+
mColumnTypeThread = new QgsGeomColumnTypeThread();
603+
mColumnTypeThread->setConnInfo(m_connInfo);
604+
}
605+
mColumnTypeThread->setGeometryColumn(schema, table, column);
606+
type = "WAITING";
552607
}
553-
*/
554608

555-
QString full_desc = "";
556-
if (schema.length() > 0)
557-
full_desc = schema + ".";
558-
full_desc += table + " (" + column + ")";
559609
details.push_back(geomPair(full_desc, type));
560610
}
561611
ok = true;
@@ -572,13 +622,23 @@ void QgsDbSourceSelect::showHelp()
572622
{
573623
QgsContextHelp::run(context_id);
574624
}
625+
QString QgsDbSourceSelect::fullDescription(QString schema, QString table,
626+
QString column)
627+
{
628+
QString full_desc = "";
629+
if (schema.length() > 0)
630+
full_desc = schema + ".";
631+
full_desc += table + " (" + column + ")";
632+
return full_desc;
633+
}
575634
void QgsDbSourceSelect::dbChanged()
576635
{
577636
// Remember which database was selected.
578637
QSettings settings;
579638
settings.writeEntry("/PostgreSQL/connections/selected",
580639
cmbConnections->currentText());
581640
}
641+
582642
void QgsDbSourceSelect::setConnectionListPosition()
583643
{
584644
QSettings settings;
@@ -609,3 +669,41 @@ void QgsDbSourceSelect::setConnectionListPosition()
609669
cmbConnections->setCurrentItem(cmbConnections->count()-1);
610670
}
611671
}
672+
673+
void QgsGeomColumnTypeThread::setConnInfo(QString s)
674+
{
675+
mConnInfo = s;
676+
}
677+
678+
void QgsGeomColumnTypeThread::setGeometryColumn(QString schema, QString table, QString column)
679+
{
680+
schemas.push_back(schema);
681+
tables.push_back(table);
682+
columns.push_back(column);
683+
}
684+
685+
void QgsGeomColumnTypeThread::getLayerTypes()
686+
{
687+
PGconn *pd = PQconnectdb(mConnInfo.toLocal8Bit().data());
688+
if (PQstatus(pd) == CONNECTION_OK)
689+
{
690+
PQsetClientEncoding(pd, "UNICODE");
691+
692+
for (int i = 0; i < schemas.size(); ++i)
693+
{
694+
QString query = QgsDbSourceSelect::makeGeomQuery(schemas[i],
695+
tables[i],
696+
columns[i]);
697+
PGresult* gresult = PQexec(pd, query.toLocal8Bit().data());
698+
QString type;
699+
if (PQresultStatus(gresult) == PGRES_TUPLES_OK)
700+
type = PQgetvalue(gresult, 0, 0);
701+
PQclear(gresult);
702+
703+
// Now tell the layer list dialog box...
704+
emit setLayerType(schemas[i], tables[i], columns[i], type);
705+
}
706+
}
707+
708+
PQfinish(pd);
709+
}

0 commit comments

Comments
 (0)