src/plugins/spit/qgsspit.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                          qgsspit.cpp  -  description
00003                             -------------------
00004    begin                : Fri Dec 19 2003
00005    copyright            : (C) 2003 by Denis Antipov
00006    email                :
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 /* $Id: qgsspit.cpp 9502 2008-10-20 20:24:36Z timlinux $ */
00018 
00019 #include <QMessageBox>
00020 #include <QComboBox>
00021 #include <QFileDialog>
00022 #include <QProgressDialog>
00023 #include <QRegExp>
00024 #include <QFile>
00025 #include <QSettings>
00026 #include <QPixmap>
00027 #include <QHeaderView>
00028 #include <QTextCodec>
00029 #include <QList>
00030 #include <QTableWidgetItem>
00031 #include <QInputDialog>
00032 
00033 #include <iostream>
00034 
00035 #include "qgsencodingfiledialog.h"
00036 
00037 #include "qgspgutil.h"
00038 #include "qgsspit.h"
00039 #include "qgsnewconnection.h"
00040 #include "qgsdatasourceuri.h"
00041 #include "qgsmessageviewer.h"
00042 #include "spiticon.xpm"
00043 #include "qgslogger.h"
00044 
00045 // Qt implementation of alignment() + changed the numeric types to be shown on the left as well
00046 /* Is this still needed? Numbers in Qt4 table seem to be left justified by default.
00047 int Q3TableItem::alignment() const
00048 {
00049   bool num;
00050   bool ok1 = FALSE, ok2 = FALSE;
00051   ( void ) txt.toInt( &ok1 );
00052   if ( !ok1 )
00053     ( void ) txt.toDouble( &ok2 );
00054   num = ok1 || ok2;
00055 
00056   return ( num ? Qt::AlignLeft : Qt::AlignLeft ) | Qt::AlignVCenter;
00057 }
00058 */
00059 
00060 QgsSpit::QgsSpit( QWidget *parent, Qt::WFlags fl ) : QDialog( parent, fl )
00061 {
00062   setupUi( this );
00063   QPixmap icon;
00064   icon = QPixmap( spitIcon );
00065   setWindowIcon( icon );
00066 
00067   // Set up the table column headers
00068   tblShapefiles->setColumnCount( 5 );
00069   QStringList headerText;
00070   headerText << tr( "File Name" ) << tr( "Feature Class" ) << tr( "Features" )
00071   << tr( "DB Relation Name" ) << tr( "Schema" );
00072   tblShapefiles->setHorizontalHeaderLabels( headerText );
00073   tblShapefiles->verticalHeader()->hide();
00074   tblShapefiles->horizontalHeader()->setStretchLastSection( true );
00075 
00076   populateConnectionList();
00077   defSrid = -1;
00078   defGeom = "the_geom";
00079   total_features = 0;
00080 
00081   chkUseDefaultSrid->setChecked( true );
00082   chkUseDefaultGeom->setChecked( true );
00083   useDefaultSrid();
00084   useDefaultGeom();
00085 
00086   txtPrimaryKeyName->setText( "gid" );
00087 
00088   schema_list << "public";
00089   conn = NULL;
00090 
00091   // Install a delegate that provides the combo box widget for
00092   // changing the schema (but there can only be one delegate per
00093   // table, so it also provides edit widgets for the textual columns).
00094   // This needs to be done after the call to getSchema() so that
00095   // schema_list is populated.
00096   ShapefileTableDelegate* delegate = new ShapefileTableDelegate( tblShapefiles, schema_list );
00097   tblShapefiles->setItemDelegate( delegate );
00098 
00099   // Now that everything is in the table, adjust the column sizes
00100   tblShapefiles->resizeColumnsToContents();
00101 }
00102 
00103 QgsSpit::~QgsSpit()
00104 {
00105   if ( conn )
00106     PQfinish( conn );
00107 }
00108 
00109 void QgsSpit::populateConnectionList()
00110 {
00111   QSettings settings;
00112   settings.beginGroup( "/PostgreSQL/connections" );
00113   QStringList keys = settings.childGroups();
00114   QStringList::Iterator it = keys.begin();
00115   cmbConnections->clear();
00116   while ( it != keys.end() )
00117   {
00118     cmbConnections->addItem( *it );
00119     ++it;
00120   }
00121   settings.endGroup();
00122 }
00123 
00124 void QgsSpit::newConnection()
00125 {
00126   QgsNewConnection *nc = new QgsNewConnection( this );
00127 
00128   if ( nc->exec() )
00129   {
00130     populateConnectionList();
00131   }
00132 }
00133 
00134 void QgsSpit::editConnection()
00135 {
00136   QgsNewConnection *nc = new QgsNewConnection( this, cmbConnections->currentText() );
00137 
00138   if ( nc->exec() )
00139   {
00140     nc->saveConnection();
00141   }
00142 }
00143 
00144 void QgsSpit::removeConnection()
00145 {
00146   QSettings settings;
00147   QString key = "/PostgreSQL/connections/" + cmbConnections->currentText();
00148   QString msg = tr( "Are you sure you want to remove the [" ) + cmbConnections->currentText() + tr( "] connection and all associated settings?" );
00149   QMessageBox::StandardButton result = QMessageBox::information( this, tr( "Confirm Delete" ), msg, QMessageBox::Ok | QMessageBox::Cancel );
00150   if ( result == QMessageBox::Ok )
00151   {
00152     settings.remove( key + "/host" );
00153     settings.remove( key + "/database" );
00154     settings.remove( key + "/port" );
00155     settings.remove( key + "/username" );
00156     settings.remove( key + "/password" );
00157     settings.remove( key + "/save" );
00158 
00159     cmbConnections->removeItem( cmbConnections->currentIndex() );
00160   }
00161 }
00162 
00163 void QgsSpit::addFile()
00164 {
00165   QString error1 = "";
00166   QString error2 = "";
00167   bool exist;
00168   bool is_error = false;
00169   QSettings settings;
00170 
00171   QgsEncodingFileDialog dlg( this,
00172                              tr( "Add Shapefiles" ),
00173                              settings.value( "/Plugin-Spit/last_directory" ).toString(),
00174                              tr( "Shapefiles (*.shp);;All files (*.*)" ),
00175                              settings.value( "/Plugin-Spit/last_encoding" ).toString() );
00176   dlg.setFileMode( QFileDialog::ExistingFiles );
00177 
00178   if ( dlg.exec() != QDialog::Accepted )
00179     return;
00180   QStringList files = dlg.selectedFiles();
00181 
00182   if ( files.size() > 0 )
00183   {
00184     // Save the directory for future use
00185     QFileInfo fi( files[ 0 ] );
00186     settings.setValue( "/Plugin-Spit/last_directory", fi.absolutePath() );
00187     settings.setValue( "/Plugin-Spit/last_encoding", dlg.encoding() );
00188   }
00189   // Process the files
00190   for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it )
00191   {
00192     exist = false;
00193     is_error = false;
00194 
00195     // Check to ensure that we don't insert the same file twice
00196     QList<QTableWidgetItem*> items = tblShapefiles->findItems( *it,
00197                                      Qt::MatchExactly );
00198     if ( items.count() > 0 )
00199     {
00200       exist = true;
00201     }
00202 
00203     if ( !exist )
00204     {
00205       // check other files: file.dbf and file.shx
00206       QString name = *it;
00207       if ( !QFile::exists( name.left( name.length() - 3 ) + "dbf" ) )
00208       {
00209         is_error = true;
00210       }
00211       else if ( !QFile::exists( name.left( name.length() - 3 ) + "shx" ) )
00212       {
00213         is_error = true;
00214       }
00215 
00216       if ( !is_error )
00217       {
00218         QgsShapeFile * file = new QgsShapeFile( name, dlg.encoding() );
00219         if ( file->is_valid() )
00220         {
00221           /* XXX getFeatureClass actually does a whole bunch
00222            * of things and is probably better named
00223            * something else
00224            */
00225           QString featureClass = file->getFeatureClass();
00226           fileList.push_back( file );
00227 
00228           QTableWidgetItem *fileNameItem       = new QTableWidgetItem( name );
00229           QTableWidgetItem *featureClassItem   = new QTableWidgetItem( featureClass );
00230           QTableWidgetItem *featureCountItem   = new QTableWidgetItem( QString( "%1" ).arg( file->getFeatureCount() ) );
00231           // Sanitize the relation name to make it pg friendly
00232           QString relName = file->getTable().replace( QRegExp( "\\s" ), "_" );
00233           QTableWidgetItem *dbRelationNameItem = new QTableWidgetItem( relName );
00234           QTableWidgetItem *dbSchemaNameItem   = new QTableWidgetItem( cmbSchema->currentText() );
00235 
00236           // All items are editable except for these two
00237           fileNameItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
00238           featureCountItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
00239 
00240           int row = tblShapefiles->rowCount();
00241           tblShapefiles->insertRow( row );
00242           tblShapefiles->setItem( row, ColFILENAME, fileNameItem );
00243           tblShapefiles->setItem( row, ColFEATURECLASS, featureClassItem );
00244           tblShapefiles->setItem( row, ColFEATURECOUNT, featureCountItem );
00245           tblShapefiles->setItem( row, ColDBRELATIONNAME, dbRelationNameItem );
00246           tblShapefiles->setItem( row, ColDBSCHEMA, dbSchemaNameItem );
00247 
00248           total_features += file->getFeatureCount();
00249         }
00250         else
00251         {
00252           error1 += name + "\n";
00253           is_error = true;
00254           delete file;
00255         }
00256       }
00257       else
00258       {
00259         error2 += name + "\n";
00260       }
00261     }
00262   }
00263 
00264   tblShapefiles->resizeColumnsToContents();
00265 
00266   if ( error1 != "" || error2 != "" )
00267   {
00268     QString message = tr( "The following Shapefile(s) could not be loaded:\n\n" );
00269     if ( error1 != "" )
00270     {
00271       error1 += "----------------------------------------------------------------------------------------";
00272       error1 += "\n" + tr( "REASON: File cannot be opened" ) + "\n\n";
00273     }
00274     if ( error2 != "" )
00275     {
00276       error2 += "----------------------------------------------------------------------------------------";
00277       error2 += "\n" + tr( "REASON: One or both of the Shapefile files (*.dbf, *.shx) missing" ) + "\n\n";
00278     }
00279     QgsMessageViewer * e = new QgsMessageViewer( this );
00280     e->setMessageAsPlainText( message + error1 + error2 );
00281     e->exec(); // deletes itself on close
00282   }
00283 }
00284 
00285 void QgsSpit::removeFile()
00286 {
00287   std::vector <int> temp;
00288   for ( int n = 0; n < tblShapefiles->rowCount(); n++ )
00289     if ( tblShapefiles->isItemSelected( tblShapefiles->item( n, 0 ) ) )
00290     {
00291       for ( std::vector<QgsShapeFile *>::iterator vit = fileList.begin(); vit != fileList.end(); vit++ )
00292       {
00293         if (( *vit ) ->getName() == tblShapefiles->item( n, 0 )->text() )
00294         {
00295           total_features -= ( *vit ) ->getFeatureCount();
00296           fileList.erase( vit );
00297           temp.push_back( n );
00298           break;
00299         }
00300       }
00301     }
00302 
00303   for ( int i = temp.size() - 1; i >= 0; --i )
00304     tblShapefiles->removeRow( temp[ i ] );
00305 
00306   QList<QTableWidgetItem*> selected = tblShapefiles->selectedItems();
00307   for ( int i = 0; i < selected.count(); ++i )
00308     selected[i]->setSelected( false );
00309 }
00310 
00311 void QgsSpit::removeAllFiles()
00312 {
00313   int i = tblShapefiles->rowCount() - 1;
00314   for ( ; i >= 0; --i )
00315     tblShapefiles->removeRow( i );
00316 
00317   fileList.clear();
00318   total_features = 0;
00319 }
00320 
00321 void QgsSpit::useDefaultSrid()
00322 {
00323   if ( chkUseDefaultSrid->isChecked() )
00324   {
00325     defaultSridValue = spinSrid->value();
00326     spinSrid->setValue( defSrid );
00327     spinSrid->setEnabled( false );
00328   }
00329   else
00330   {
00331     spinSrid->setEnabled( true );
00332     spinSrid->setValue( defaultSridValue );
00333   }
00334 }
00335 
00336 void QgsSpit::useDefaultGeom()
00337 {
00338   if ( chkUseDefaultGeom->isChecked() )
00339   {
00340     defaultGeomValue = txtGeomName->text();
00341     txtGeomName->setText( defGeom );
00342     txtGeomName->setEnabled( false );
00343   }
00344   else
00345   {
00346     txtGeomName->setEnabled( true );
00347     txtGeomName->setText( defaultGeomValue );
00348   }
00349 }
00350 
00351 // TODO: make translation of helpinfo
00352 void QgsSpit::helpInfo()
00353 {
00354   QString message = tr( "General Interface Help:" ) + "\n\n";
00355   message += QString(
00356                tr( "PostgreSQL Connections:" ) + "\n" ) + QString(
00357                "----------------------------------------------------------------------------------------\n" ) + QString(
00358                tr( "[New ...] - create a new connection" ) + "\n" ) + QString(
00359                tr( "[Edit ...] - edit the currently selected connection" ) + "\n" ) + QString(
00360                tr( "[Remove] - remove the currently selected connection" ) + "\n" ) + QString(
00361                tr( "-you need to select a connection that works (connects properly) in order to import files" ) + "\n" ) + QString(
00362                tr( "-when changing connections Global Schema also changes accordingly" ) + "\n\n" ) + QString(
00363                tr( "Shapefile List:" ) + "\n" ) + QString(
00364                "----------------------------------------------------------------------------------------\n" ) + QString(
00365                tr( "[Add ...] - open a File dialog and browse to the desired file(s) to import" ) + "\n" ) + QString(
00366                tr( "[Remove] - remove the currently selected file(s) from the list" ) + "\n" ) + QString(
00367                tr( "[Remove All] - remove all the files in the list" ) + "\n" ) + QString(
00368                tr( "[SRID] - Reference ID for the shapefiles to be imported" ) + "\n" ) + QString(
00369                tr( "[Use Default (SRID)] - set SRID to -1" ) + "\n" ) + QString(
00370                tr( "[Geometry Column Name] - name of the geometry column in the database" ) + "\n" ) + QString(
00371                tr( "[Use Default (Geometry Column Name)] - set column name to \'the_geom\'" ) + "\n" ) + QString(
00372                tr( "[Glogal Schema] - set the schema for all files to be imported into" ) + "\n\n" ) + QString(
00373                "----------------------------------------------------------------------------------------\n" ) + QString(
00374                tr( "[Import] - import the current shapefiles in the list" ) + "\n" ) + QString(
00375                tr( "[Quit] - quit the program\n" ) ) + QString(
00376                tr( "[Help] - display this help dialog" ) + "\n\n" );
00377   QgsMessageViewer * e = new QgsMessageViewer( this );
00378   e->setMessageAsPlainText( message );
00379   e->exec(); // deletes itself on close
00380 }
00381 
00382 void QgsSpit::dbConnect()
00383 {
00384   if ( conn )
00385   {
00386     PQfinish( conn );
00387     conn = NULL;
00388   }
00389 
00390   QSettings settings;
00391   QString connName = cmbConnections->currentText();
00392   if ( connName.isEmpty() )
00393   {
00394     QMessageBox::warning( this, tr( "Import Shapefiles" ), tr( "You need to specify a Connection first" ) );
00395     return;
00396   }
00397 
00398   QString key = "/PostgreSQL/connections/" + connName;
00399   QString database = settings.value( key + "/database" ).toString();
00400   QString username = settings.value( key + "/username" ).toString();
00401   QString password = settings.value( key + "/password" ).toString();
00402 
00403   bool makeConnection = true;
00404 
00405   if ( password.isEmpty() )
00406   {
00407     // get password from user
00408     password = QInputDialog::getText( this, tr( "Password for " ) + username,
00409                                       tr( "Please enter your password:" ),
00410                                       QLineEdit::Password, QString::null, &makeConnection );
00411   }
00412 
00413   if ( makeConnection )
00414   {
00415     // allow null password entry in case its valid for the database
00416     QgsDataSourceURI uri;
00417     uri.setConnection( settings.value( key + "/host" ).toString(),
00418                        settings.value( key + "/port" ).toString(),
00419                        database,
00420                        settings.value( key + "/username" ).toString(),
00421                        password );
00422 
00423     conn = PQconnectdb( uri.connectionInfo().toUtf8() );
00424   }
00425 
00426   if ( conn == NULL || PQstatus( conn ) != CONNECTION_OK )
00427   {
00428     QMessageBox::warning( this, tr( "Import Shapefiles" ), tr( "Connection failed - Check settings and try again" ) );
00429     if ( conn )
00430     {
00431       PQfinish( conn );
00432       conn = 0;
00433     }
00434   }
00435 
00436   schema_list.clear();
00437   schema_list << "public";
00438 
00439   if ( conn )
00440   {
00441     int errcode = PQsetClientEncoding( conn, QString( "UNICODE" ).toLocal8Bit() );
00442     if ( errcode == 0 )
00443     {
00444       QgsDebugMsg( "encoding successfully set" );
00445     }
00446     else if ( errcode == -1 )
00447     {
00448       QgsDebugMsg( "error in setting encoding" );
00449     }
00450     else
00451     {
00452       QgsDebugMsg( "undefined return value from encoding setting" );
00453     }
00454 
00455     // Check that the database actually has postgis in it.
00456     QString sql1 = "SELECT postgis_lib_version()"; // available from v 0.9.0 onwards
00457     QString sql2 = "SELECT postgis_version()"; // depreciated
00458 
00459     PGresult* ver = PQexec( conn, sql1.toUtf8() );
00460     if ( PQresultStatus( ver ) != PGRES_TUPLES_OK )
00461     {
00462       // In case the version of postgis is older than 0.9.0, try the
00463       // depreciated call before erroring out.
00464       PQclear( ver );
00465       ver = PQexec( conn, sql2.toUtf8() );
00466       if ( PQresultStatus( ver ) != PGRES_TUPLES_OK )
00467       {
00468         QMessageBox::warning( this, tr( "PostGIS not available" ),
00469                               tr( "<p>The chosen database does not have PostGIS installed, "
00470                                   "but this is required for storage of spatial data.</p>" ) );
00471       }
00472     }
00473 
00474     QString schemaSql = QString( "select nspname from pg_namespace,pg_user where nspowner=usesysid and usename=%1" )
00475                         .arg( QgsPgUtil::quotedValue( username ) );
00476     PGresult *schemas = PQexec( conn, schemaSql.toUtf8() );
00477     // get the schema names
00478     if ( PQresultStatus( schemas ) == PGRES_TUPLES_OK )
00479     {
00480       for ( int i = 0; i < PQntuples( schemas ); i++ )
00481       {
00482         if ( QString( PQgetvalue( schemas, i, 0 ) ) != "public" )
00483           schema_list << QString( PQgetvalue( schemas, i, 0 ) );
00484       }
00485     }
00486     PQclear( schemas );
00487   }
00488 
00489   // install a new delegate with an updated schema list (rather than
00490   // update the existing delegate because delegates don't seem able to
00491   // store modifiable data).
00492   ShapefileTableDelegate* delegate = new ShapefileTableDelegate( tblShapefiles, schema_list );
00493   tblShapefiles->setItemDelegate( delegate );
00494 
00495   cmbSchema->clear();
00496   cmbSchema->insertItems( 0, schema_list );
00497   cmbSchema->setCurrentIndex( 0 ); // index 0 is always "public"
00498 }
00499 
00500 void QgsSpit::import()
00501 {
00502   QList<QTableWidgetItem*> selected = tblShapefiles->selectedItems();
00503   for ( int i = 0; i < selected.count(); ++i )
00504     selected[i]->setSelected( false );
00505 
00506   QString connName = cmbConnections->currentText();
00507   QSettings settings;
00508   bool canceled = false;
00509 
00510   QString query;
00511   if ( total_features == 0 )
00512   {
00513     QMessageBox::warning( this, tr( "Import Shapefiles" ),
00514                           tr( "You need to add shapefiles to the list first" ) );
00515   }
00516   else if ( conn != NULL )
00517   {
00518     PGresult * res;
00519     QProgressDialog pro( tr( "Importing files" ), tr( "Cancel" ),
00520                          0, total_features, this );
00521 
00522     pro.setValue( 0 );
00523     pro.setLabelText( tr( "Progress" ) );
00524     pro.setAutoClose( true );
00525     //pro->show();
00526     qApp->processEvents();
00527 
00528     int count = fileList.size(), successes = 0;
00529 
00530     for ( std::vector<QgsShapeFile*>::size_type i = 0; i < fileList.size() ; i++ )
00531     {
00532       QString error = tr( "Problem inserting features from file:" ) + "\n" +
00533                       tblShapefiles->item( i, ColFILENAME )->text();
00534 
00535       // if a name starts with invalid character
00536       if ( ! tblShapefiles->item( i, ColDBRELATIONNAME )->text()[ 0 ].isLetter() )
00537       {
00538         QMessageBox::warning( &pro, tr( "Import Shapefiles" ),
00539                               error + "\n" + tr( "Invalid table name." ) );
00540         pro.setValue( pro.value()
00541                       + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00542         continue;
00543       }
00544 
00545       // if no fields detected
00546       if (( fileList[ i ] ->column_names ).size() == 0 )
00547       {
00548         QMessageBox::warning( &pro, tr( "Import Shapefiles" ),
00549                               error + "\n" + tr( "No fields detected." ) );
00550         pro.setValue( pro.value() +
00551                       tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00552         continue;
00553       }
00554 
00555       // duplicate field check
00556       std::vector<QString> names_copy = fileList[ i ] ->column_names;
00557       names_copy.push_back( txtPrimaryKeyName->text() );
00558       names_copy.push_back( txtGeomName->text() );
00559 
00560       QString dupl = "";
00561       std::sort( names_copy.begin(), names_copy.end() );
00562 
00563       for ( std::vector<QString>::size_type k = 1; k < names_copy.size(); k++ )
00564       {
00565         QgsDebugMsg( QString( "Checking to see if %1 == %2" ).arg( names_copy[ k ] ).arg( names_copy[ k - 1 ] ) );
00566         if ( names_copy[ k ] == names_copy[ k - 1 ] )
00567           dupl += names_copy[ k ] + "\n";
00568       }
00569 
00570       // if duplicate field names exist
00571       if ( dupl != "" )
00572       {
00573         QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error +
00574                               "\n" + tr( "The following fields are duplicates:" ) + "\n" + dupl );
00575         pro.setValue( pro.value() + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00576         continue;
00577       }
00578 
00579       // Check and set destination table
00580       fileList[ i ] ->setTable( tblShapefiles->item( i, ColDBRELATIONNAME )->text() );
00581       pro.setLabelText( tr( "Importing files" ) + "\n"
00582                         + tblShapefiles->item( i, ColFILENAME )->text() );
00583       bool rel_exists1 = false;
00584       bool rel_exists2 = false;
00585       query = QString( "SELECT f_table_name FROM geometry_columns WHERE f_table_name=%1 AND f_table_schema=%2" )
00586               .arg( QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBRELATIONNAME )->text() ) )
00587               .arg( QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBSCHEMA )->text() ) );
00588       res = PQexec( conn, query.toUtf8() );
00589       rel_exists1 = ( PQntuples( res ) > 0 );
00590 
00591       if ( PQresultStatus( res ) != PGRES_TUPLES_OK )
00592       {
00593         QString err = PQresultErrorMessage( res );
00594         QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00595                               tr( "<p>Error while executing the SQL:</p><p>" ) +
00596                               query + tr( "</p><p>The database said:" ) +
00597                               err + "</p>" );
00598         pro.setValue( pro.value() + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00599         PQclear( res );
00600         continue;
00601       }
00602 
00603       PQclear( res );
00604 
00605       query = QString( "SELECT tablename FROM pg_tables WHERE tablename=%1  AND schemaname=%2" )
00606               .arg( QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBRELATIONNAME )->text() ) )
00607               .arg( QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBSCHEMA )->text() ) );
00608       res = PQexec( conn, query.toUtf8() );
00609 
00610       rel_exists2 = ( PQntuples( res ) > 0 );
00611 
00612       if ( PQresultStatus( res ) != PGRES_TUPLES_OK )
00613       {
00614         QString err = PQresultErrorMessage( res );
00615         QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00616                               tr( "<p>Error while executing the SQL:</p><p>" ) +
00617                               query + tr( "</p><p>The database said:" ) +
00618                               err + "</p>" );
00619 
00620         pro.setValue( pro.value() + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00621         PQclear( res );
00622         continue;
00623       }
00624       else
00625       {
00626         PQclear( res );
00627       }
00628 
00629       // begin session
00630       query = "BEGIN";
00631       res = PQexec( conn, query.toUtf8() );
00632       if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
00633       {
00634         QString err = PQresultErrorMessage( res );
00635         QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00636                               tr( "<p>Error while executing the SQL:</p><p>" ) +
00637                               query + tr( "</p><p>The database said:" ) +
00638                               err + "</p>" );
00639         pro.setValue( pro.value() + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00640         PQclear( res );
00641         continue;
00642       }
00643       else
00644       {
00645         PQclear( res );
00646       }
00647 
00648       query = "SET SEARCH_PATH TO ";
00649       if ( !tblShapefiles->item( i, ColDBSCHEMA )->text().isEmpty() &&
00650            tblShapefiles->item( i, ColDBSCHEMA )->text() != "public" )
00651         query += QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBSCHEMA )->text() ) + ",";
00652       query += QgsPgUtil::quotedValue( "public" );
00653       res = PQexec( conn, query.toUtf8() );
00654 
00655       if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
00656       {
00657         QString err = PQresultErrorMessage( res );
00658         QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00659                               tr( "<p>Error while executing the SQL:</p><p>" ) +
00660                               query + tr( "</p><p>The database said:" ) +
00661                               err + "</p>" );
00662         pro.setValue( pro.value() + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00663         PQclear( res );
00664         continue;
00665       }
00666       else
00667       {
00668         PQclear( res );
00669       }
00670 
00671       if ( rel_exists1 || rel_exists2 )
00672       {
00673         QMessageBox::StandardButton del_confirm = QMessageBox::warning( this,
00674             tr( "Import Shapefiles - Relation Exists" ),
00675             tr( "The Shapefile:" ) + "\n" + tblShapefiles->item( i, 0 )->text() + "\n" + tr( "will use [" ) +
00676             tblShapefiles->item( i, ColDBRELATIONNAME )->text() + tr( "] relation for its data," ) + "\n" + tr( "which already exists and possibly contains data." ) + "\n" +
00677             tr( "To avoid data loss change the \"DB Relation Name\"" ) + "\n" + tr( "for this Shapefile in the main dialog file list." ) + "\n\n" +
00678             tr( "Do you want to overwrite the [" ) + tblShapefiles->item( i, ColDBRELATIONNAME )->text() + tr( "] relation?" ),
00679             QMessageBox::Ok | QMessageBox::Cancel );
00680 
00681         if ( del_confirm == QMessageBox::Ok )
00682         {
00683           if ( rel_exists2 )
00684           {
00685             query = QString( "DROP TABLE %1" )
00686                     .arg( QgsPgUtil::quotedIdentifier( tblShapefiles->item( i, ColDBRELATIONNAME )->text() ) );
00687 
00688             res = PQexec( conn, query.toUtf8() );
00689             if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
00690             {
00691               QString err = PQresultErrorMessage( res );
00692               QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00693                                     tr( "<p>Error while executing the SQL:</p><p>" ) +
00694                                     query + tr( "</p><p>The database said:" ) +
00695                                     err + "</p>" );
00696               pro.setValue( pro.value() + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00697               PQclear( res );
00698               continue;
00699             }
00700             else
00701             {
00702               PQclear( res );
00703             }
00704           }
00705 
00706           if ( rel_exists1 )
00707           {
00708             query = QString( "SELECT f_geometry_column FROM geometry_columns WHERE f_table_schema=%1 AND f_table_name=%2" )
00709                     .arg( QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBSCHEMA )->text() ) )
00710                     .arg( QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBRELATIONNAME )->text() ) );
00711 
00712             QStringList columns;
00713             res = PQexec( conn, query.toUtf8() );
00714             if ( PQresultStatus( res ) != PGRES_TUPLES_OK )
00715             {
00716               for ( int i = 0; i < PQntuples( res ); i++ )
00717                 columns.append( PQgetvalue( res, i, 0 ) );
00718             }
00719             PQclear( res );
00720 
00721             for ( int i = 0; i < columns.size(); i++ )
00722             {
00723               query = QString( "SELECT DropGeometryColumn(%1,%2,%3)" )
00724                       .arg( QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBSCHEMA )->text() ) )
00725                       .arg( QgsPgUtil::quotedValue( tblShapefiles->item( i, ColDBRELATIONNAME )->text() ) )
00726                       .arg( QgsPgUtil::quotedValue( columns[i] ) );
00727 
00728               res = PQexec( conn, query.toUtf8() );
00729               if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
00730               {
00731                 QString err = PQresultErrorMessage( res );
00732                 QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00733                                       tr( "<p>Error while executing the SQL:</p><p>" ) +
00734                                       query + tr( "</p><p>The database said:" ) +
00735                                       err + "</p>" );
00736                 pro.setValue( pro.value() + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00737               }
00738 
00739               PQclear( res );
00740             }
00741           }
00742         }
00743         else
00744         {
00745           query = "ROLLBACK";
00746           res = PQexec( conn, query.toUtf8() );
00747           if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
00748           {
00749             QString err = PQresultErrorMessage( res );
00750             QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00751                                   tr( "<p>Error while executing the SQL:</p><p>" ) +
00752                                   query + tr( "</p><p>The database said:" ) +
00753                                   err + "</p>" );
00754           }
00755           PQclear( res );
00756 
00757           pro.setValue( pro.value() + tblShapefiles->item( i, 2 )->text().toInt() );
00758           continue;
00759         }
00760       }
00761 
00762       // importing file here
00763       int temp_progress = pro.value();
00764       canceled = false;
00765 
00766       QString key = "/PostgreSQL/connections/" + connName;
00767       QString dbname = settings.value( key + "/database" ).toString();
00768       QString schema = tblShapefiles->item( i, ColDBSCHEMA )->text();
00769       QString srid = QString( "%1" ).arg( spinSrid->value() );
00770       QString errorText;
00771 
00772       bool layerInserted = fileList[i]->insertLayer( dbname, schema, txtPrimaryKeyName->text(), txtGeomName->text(), srid, conn, pro, canceled, errorText );
00773       if ( layerInserted && !canceled )
00774       { // if file has been imported successfully
00775         query = "COMMIT";
00776         res = PQexec( conn, query.toUtf8() );
00777         if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
00778         {
00779           QString err = PQresultErrorMessage( res );
00780           QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00781                                 tr( "<p>Error while executing the SQL:</p><p>" ) +
00782                                 query + tr( "</p><p>The database said:" ) +
00783                                 err + "</p>" );
00784           PQclear( res );
00785           continue;
00786         }
00787 
00788         PQclear( res );
00789 
00790         // remove file
00791         for ( int j = 0; j < tblShapefiles->rowCount(); j++ )
00792         {
00793           if ( tblShapefiles->item( j, ColFILENAME )->text() == QString( fileList[ i ] ->getName() ) )
00794           {
00795             tblShapefiles->selectRow( j );
00796             removeFile();
00797             i--;
00798             break;
00799           }
00800         }
00801 
00802         successes++;
00803       }
00804       else if ( !canceled )
00805       { // if problem importing file occured
00806         pro.setValue( temp_progress + tblShapefiles->item( i, ColFEATURECOUNT )->text().toInt() );
00807         QString errTxt = error + "\n" + errorText;
00808         QMessageBox::warning( this, tr( "Import Shapefiles" ), errTxt );
00809         query = "ROLLBACK";
00810         res = PQexec( conn, query.toUtf8() );
00811         if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
00812         {
00813           QString err = PQresultErrorMessage( res );
00814           QMessageBox::warning( &pro, tr( "Import Shapefiles" ), error + "\n" +
00815                                 tr( "<p>Error while executing the SQL:</p><p>" ) +
00816                                 query + tr( "</p><p>The database said:" ) +
00817                                 err + "</p>" );
00818         }
00819 
00820         PQclear( res );
00821       }
00822       else
00823       { // if import was actually canceled
00824         break;
00825       }
00826     }
00827 
00828     if ( successes == count )
00829       accept();
00830     else
00831       QMessageBox::information( &pro, tr( "Import Shapefiles" ), QString( tr( "%1 of %2 shapefiles could not be imported." ) ).arg( count - successes ).arg( count ) );
00832   }
00833   else
00834   {
00835     QMessageBox::warning( this, tr( "Import Shapefiles" ), tr( "You need to specify a Connection first" ) );
00836   }
00837 }
00838 
00839 QWidget *ShapefileTableDelegate::createEditor( QWidget *parent,
00840     const QStyleOptionViewItem &,
00841     const QModelIndex & index ) const
00842 {
00843   switch ( index.column() )
00844   {
00845     case 4:
00846     {
00847       QComboBox* editor = new QComboBox( parent );
00848       editor->setSizeAdjustPolicy( QComboBox::AdjustToContents );
00849       editor->installEventFilter( const_cast<ShapefileTableDelegate*>( this ) );
00850       return editor;
00851       break;
00852     }
00853     case 1:
00854     case 3:
00855     {
00856       QLineEdit* editor = new QLineEdit( parent );
00857       editor->installEventFilter( const_cast<ShapefileTableDelegate*>( this ) );
00858       return editor;
00859       break;
00860     }
00861   }
00862   return NULL;
00863 }
00864 
00865 void ShapefileTableDelegate::setEditorData( QWidget *editor,
00866     const QModelIndex &index ) const
00867 {
00868   switch ( index.column() )
00869   {
00870     case 4:
00871     {
00872       // Create a combobox and populate with the list of schemas
00873       QComboBox *comboBox = static_cast<QComboBox*>( editor );
00874       comboBox->insertItems( 0, mSchemaList );
00875       // Get the text from the table and use to set the selected text
00876       // in the combo box.
00877       QString text = index.model()->data( index, Qt::DisplayRole ).toString();
00878       comboBox->setCurrentIndex( mSchemaList.indexOf( text ) );
00879       break;
00880     }
00881     case 1:
00882     case 3:
00883     {
00884       QString text = index.model()->data( index, Qt::DisplayRole ).toString();
00885       QLineEdit *lineEdit = static_cast<QLineEdit*>( editor );
00886       lineEdit->setText( text );
00887       break;
00888     }
00889   }
00890 }
00891 
00892 void ShapefileTableDelegate::setModelData( QWidget *editor, QAbstractItemModel *model,
00893     const QModelIndex &index ) const
00894 {
00895   switch ( index.column() )
00896   {
00897     case 4:
00898     {
00899       QComboBox *comboBox = static_cast<QComboBox*>( editor );
00900       QString text = comboBox->currentText();
00901       model->setData( index, text );
00902       break;
00903     }
00904     case 1:
00905     case 3:
00906     {
00907       QLineEdit *lineEdit = static_cast<QLineEdit*>( editor );
00908       QString text = lineEdit->text();
00909 
00910       model->setData( index, text );
00911       break;
00912     }
00913   }
00914 }
00915 
00916 void ShapefileTableDelegate::updateEditorGeometry( QWidget *editor,
00917     const QStyleOptionViewItem &option, const QModelIndex &/* index */ ) const
00918 {
00919   editor->setGeometry( option.rect );
00920 }

Generated on Tue Oct 28 16:51:36 2008 for Quantum GIS API Documentation by  doxygen 1.5.1