@@ -30,14 +30,13 @@ email : sherman at mrcc.com
30
30
#include < QSettings>
31
31
#include < QTextOStream>
32
32
#include < QTableWidgetItem>
33
- #include < QIcon>
34
33
#include < QHeaderView>
35
34
36
35
#include < cassert>
37
36
#include < iostream>
38
37
39
38
QgsDbSourceSelect::QgsDbSourceSelect (QgisApp *app, Qt::WFlags fl)
40
- : QDialog(app, fl), qgisApp(app)
39
+ : QDialog(app, fl), qgisApp(app), mColumnTypeThread( NULL )
41
40
{
42
41
setupUi (this );
43
42
btnAdd->setEnabled (false );
@@ -105,9 +104,9 @@ QgsDbSourceSelect::QgsDbSourceSelect(QgisApp *app, Qt::WFlags fl)
105
104
106
105
// Do some things that couldn't be done in designer
107
106
lstTables->horizontalHeader ()->setStretchLastSection (true );
107
+ QStringList labels;
108
108
// Set the column count to 3 for the type, name, and sql
109
109
lstTables->setColumnCount (3 );
110
- QStringList labels;
111
110
labels += tr (" Type" ); labels += tr (" Name" ); labels += tr (" Sql" );
112
111
lstTables->setHorizontalHeaderLabels (labels);
113
112
lstTables->verticalHeader ()->hide ();
@@ -148,6 +147,59 @@ void QgsDbSourceSelect::on_btnHelp_clicked()
148
147
}
149
148
/* * End Autoconnected SLOTS **/
150
149
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
+
151
203
QgsDbSourceSelect::~QgsDbSourceSelect ()
152
204
{
153
205
PQfinish (pd);
@@ -278,13 +330,31 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
278
330
{
279
331
// create the pixmaps for the layer types
280
332
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" )));
286
357
287
- assert (!pxPoint.isNull ());
288
358
// qDebug("Connection succeeded");
289
359
// tell the DB that we want text encoded in UTF8
290
360
PQsetClientEncoding (pd, " UNICODE" );
@@ -299,47 +369,18 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
299
369
for (; iter != details.end (); ++iter)
300
370
{
301
371
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 ))
334
375
{
335
- p = &pxWaiting ;
336
- toolTipText = tr ( " Waiting for layer type " ) ;
376
+ p = &( mLayerIcons . value (iter-> second ). second ) ;
377
+ toolTipText = mLayerIcons . value (iter-> second ). first ;
337
378
}
338
379
else
339
380
{
340
381
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 ;
343
384
}
344
385
345
386
if (p != 0 )
@@ -349,11 +390,6 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
349
390
iconItem->setToolTip (toolTipText);
350
391
QTableWidgetItem *textItem = new QTableWidgetItem (iter->first );
351
392
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 " ;
357
393
lstTables->setRowCount (row+1 );
358
394
lstTables->setItem (row, 0 , iconItem);
359
395
lstTables->setItem (row, 1 , textItem);
@@ -370,6 +406,25 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
370
406
// And tidy up the columns & rows
371
407
lstTables->resizeColumnsToContents ();
372
408
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
+ }
373
428
}
374
429
else
375
430
{
@@ -522,40 +577,35 @@ bool QgsDbSourceSelect::getGeometryColumnInfo(PGconn *pg,
522
577
QString column = PQgetvalue (result, i, 2 ); // attname
523
578
QString relkind = PQgetvalue (result, i, 3 ); // relation kind
524
579
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);
532
581
582
+ QString type = " UNKNOWN" ;
583
+ if (relkind == " r" )
584
+ {
585
+ QString query = makeGeomQuery (schema, table, column);
533
586
PGresult* gresult = PQexec (pg, query.toLocal8Bit ().data ());
534
587
if (PQresultStatus (gresult) != PGRES_TUPLES_OK)
535
588
{
536
589
QString myError = (tr (" Access to relation " ) + table + tr (" using sql;\n " ) + query +
537
590
tr (" \n has failed. The database said:\n " ));
538
591
qDebug (myError + QString (PQresultErrorMessage (gresult)));
539
- type = " UNKNOWN" ;
540
592
}
541
593
else
542
594
type = PQgetvalue (gresult, 0 , 0 ); // GeometryType
543
595
PQclear (gresult);
544
596
}
545
- /*
546
- // Commented out temporarily...
547
597
else // view
548
598
{
549
599
// 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" ;
552
607
}
553
- */
554
608
555
- QString full_desc = " " ;
556
- if (schema.length () > 0 )
557
- full_desc = schema + " ." ;
558
- full_desc += table + " (" + column + " )" ;
559
609
details.push_back (geomPair (full_desc, type));
560
610
}
561
611
ok = true ;
@@ -572,13 +622,23 @@ void QgsDbSourceSelect::showHelp()
572
622
{
573
623
QgsContextHelp::run (context_id);
574
624
}
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
+ }
575
634
void QgsDbSourceSelect::dbChanged ()
576
635
{
577
636
// Remember which database was selected.
578
637
QSettings settings;
579
638
settings.writeEntry (" /PostgreSQL/connections/selected" ,
580
639
cmbConnections->currentText ());
581
640
}
641
+
582
642
void QgsDbSourceSelect::setConnectionListPosition ()
583
643
{
584
644
QSettings settings;
@@ -609,3 +669,41 @@ void QgsDbSourceSelect::setConnectionListPosition()
609
669
cmbConnections->setCurrentItem (cmbConnections->count ()-1 );
610
670
}
611
671
}
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