Quantum GIS API Documentation
1.7.4
|
00001 #include "qgsprojectbadlayerguihandler.h" 00002 00003 #include <QApplication> 00004 #include <QDomDocument> 00005 #include <QFileInfo> 00006 #include <QMessageBox> 00007 #include <QPushButton> 00008 00009 #include "qgslogger.h" 00010 #include "qgisgui.h" 00011 #include "qgsproviderregistry.h" 00012 00013 QgsProjectBadLayerGuiHandler::QgsProjectBadLayerGuiHandler() 00014 { 00015 } 00016 00017 bool QgsProjectBadLayerGuiHandler::mIgnore = false; 00018 00019 void QgsProjectBadLayerGuiHandler::handleBadLayers( QList<QDomNode> layers, QDomDocument projectDom ) 00020 { 00021 QgsDebugMsg( QString( "%1 bad layers found" ).arg( layers.size() ) ); 00022 00023 // make sure we have arrow cursor (and not a wait cursor) 00024 QApplication::setOverrideCursor( Qt::ArrowCursor ); 00025 00026 QMessageBox messageBox; 00027 00028 QAbstractButton *ignoreButton = 00029 messageBox.addButton( tr( "Ignore" ), QMessageBox::ActionRole ); 00030 00031 QAbstractButton *okButton = messageBox.addButton( QMessageBox :: Ok ); 00032 00033 messageBox.addButton( QMessageBox :: Cancel ); 00034 00035 messageBox.setWindowTitle( tr( "QGIS Project Read Error" ) ); 00036 messageBox.setText( tr( "Unable to open one or more project layers.\nChoose " 00037 "ignore to continue loading without the missing layers. Choose cancel to " 00038 "return to your pre-project load state. Choose OK to try to find the " 00039 "missing layers." ) ); 00040 messageBox.setIcon( QMessageBox::Critical ); 00041 messageBox.exec(); 00042 00043 QgsProjectBadLayerGuiHandler::mIgnore = false; 00044 00045 if ( messageBox.clickedButton() == okButton ) 00046 { 00047 QgsDebugMsg( "want to find missing layers is true" ); 00048 00049 // attempt to find the new locations for missing layers 00050 // XXX vector file hard-coded -- but what if it's raster? 00051 00052 QString filter = QgsProviderRegistry::instance()->fileVectorFilters(); 00053 findLayers( filter, layers ); 00054 } 00055 else if ( messageBox.clickedButton() == ignoreButton ) 00056 { 00057 QgsProjectBadLayerGuiHandler::mIgnore = true; 00058 } 00059 else 00060 { 00061 // Do nothing 00062 } 00063 00064 QApplication::restoreOverrideCursor(); 00065 } 00066 00067 QgsProjectBadLayerGuiHandler::DataType QgsProjectBadLayerGuiHandler::dataType( QDomNode & layerNode ) 00068 { 00069 QString type = layerNode.toElement().attribute( "type" ); 00070 00071 if ( QString::null == type ) 00072 { 00073 QgsDebugMsg( "cannot find ``type'' attribute" ); 00074 00075 return IS_BOGUS; 00076 } 00077 00078 if ( "raster" == type ) 00079 { 00080 QgsDebugMsg( "is a raster" ); 00081 00082 return IS_RASTER; 00083 } 00084 else if ( "vector" == type ) 00085 { 00086 QgsDebugMsg( "is a vector" ); 00087 00088 return IS_VECTOR; 00089 } 00090 00091 QgsDebugMsg( "is unknown type " + type ); 00092 00093 return IS_BOGUS; 00094 } // dataType_( QDomNode & layerNode ) 00095 00096 00097 QString QgsProjectBadLayerGuiHandler::dataSource( QDomNode & layerNode ) 00098 { 00099 QDomNode dataSourceNode = layerNode.namedItem( "datasource" ); 00100 00101 if ( dataSourceNode.isNull() ) 00102 { 00103 QgsDebugMsg( "cannot find datasource node" ); 00104 00105 return QString::null; 00106 } 00107 00108 return dataSourceNode.toElement().text(); 00109 00110 } // dataSource( QDomNode & layerNode ) 00111 00112 00113 00114 00115 QgsProjectBadLayerGuiHandler::ProviderType QgsProjectBadLayerGuiHandler::providerType( QDomNode & layerNode ) 00116 { 00117 // XXX but what about rasters that can be URLs? _Can_ they be URLs? 00118 00119 switch ( dataType( layerNode ) ) 00120 { 00121 case IS_VECTOR: 00122 { 00123 QString ds = dataSource( layerNode ); 00124 00125 QgsDebugMsg( "datasource is " + ds ); 00126 00127 if ( ds.contains( "host=" ) ) 00128 { 00129 return IS_URL; 00130 } 00131 #ifdef HAVE_POSTGRESQL 00132 else if ( ds.contains( "dbname=" ) ) 00133 { 00134 return IS_DATABASE; 00135 } 00136 #endif 00137 // be default, then, this should be a file based layer data source 00138 // XXX is this a reasonable assumption? 00139 00140 return IS_FILE; 00141 } 00142 00143 case IS_RASTER: // rasters are currently only accessed as 00144 // physical files 00145 return IS_FILE; 00146 00147 default: 00148 QgsDebugMsg( "unknown ``type'' attribute" ); 00149 } 00150 00151 return IS_Unknown; 00152 00153 } // providerType 00154 00155 00156 00157 void QgsProjectBadLayerGuiHandler::setDataSource( QDomNode & layerNode, QString const & dataSource ) 00158 { 00159 QDomNode dataSourceNode = layerNode.namedItem( "datasource" ); 00160 QDomElement dataSourceElement = dataSourceNode.toElement(); 00161 QDomText dataSourceText = dataSourceElement.firstChild().toText(); 00162 00163 QgsDebugMsg( "datasource changed from " + dataSourceText.data() ); 00164 00165 dataSourceText.setData( dataSource ); 00166 00167 QgsDebugMsg( "to " + dataSourceText.data() ); 00168 } // setDataSource 00169 00170 00171 00172 00173 bool QgsProjectBadLayerGuiHandler::findMissingFile( QString const & fileFilters, QDomNode & layerNode ) 00174 { 00175 // Prepend that file name to the valid file format filter list since it 00176 // makes it easier for the user to not only find the original file, but to 00177 // perhaps find a similar file. 00178 00179 QFileInfo originalDataSource( dataSource( layerNode ) ); 00180 00181 QString memoryQualifier; // to differentiate between last raster and 00182 // vector directories 00183 00184 switch ( dataType( layerNode ) ) 00185 { 00186 case IS_VECTOR: 00187 { 00188 memoryQualifier = "lastVectorFileFilter"; 00189 00190 break; 00191 } 00192 case IS_RASTER: 00193 { 00194 memoryQualifier = "lastRasterFileFilter"; 00195 00196 break; 00197 } 00198 default: 00199 QgsDebugMsg( "unable to determine data type" ); 00200 return false; 00201 } 00202 00203 // Prepend the original data source base name to make it easier to pick it 00204 // out from a list of other files; however the appropriate filter strings 00205 // for the file type will also be added in case the file name itself has 00206 // changed, too. 00207 00208 QString myFileFilters = originalDataSource.fileName() + ";;" + fileFilters; 00209 00210 QStringList selectedFiles; 00211 QString enc; 00212 QString title = QObject::tr( "Where is '%1' (original location: %2)?" ) 00213 .arg( originalDataSource.fileName() ) 00214 .arg( originalDataSource.absoluteFilePath() ); 00215 00216 bool retVal = QgisGui::openFilesRememberingFilter( memoryQualifier, 00217 myFileFilters, 00218 selectedFiles, 00219 enc, 00220 title, 00221 true ); 00222 00223 if ( selectedFiles.isEmpty() ) 00224 { 00225 return retVal; 00226 } 00227 else 00228 { 00229 setDataSource( layerNode, selectedFiles.first() ); 00230 if ( ! QgsProject::instance()->read( layerNode ) ) 00231 { 00232 QgsDebugMsg( "unable to re-read layer" ); 00233 } 00234 } 00235 return retVal; 00236 } // findMissingFile 00237 00238 00239 00240 00241 bool QgsProjectBadLayerGuiHandler::findLayer( QString const & fileFilters, QDomNode const & constLayerNode ) 00242 { 00243 // XXX actually we could possibly get away with a copy of the node 00244 QDomNode & layerNode = const_cast<QDomNode&>( constLayerNode ); 00245 00246 bool retVal = false; 00247 00248 switch ( providerType( layerNode ) ) 00249 { 00250 case IS_FILE: 00251 QgsDebugMsg( "layer is file based" ); 00252 retVal = findMissingFile( fileFilters, layerNode ); 00253 break; 00254 00255 case IS_DATABASE: 00256 QgsDebugMsg( "layer is database based" ); 00257 break; 00258 00259 case IS_URL: 00260 QgsDebugMsg( "layer is URL based" ); 00261 break; 00262 00263 case IS_Unknown: 00264 QgsDebugMsg( "layer has an unknown type" ); 00265 break; 00266 } 00267 return retVal; 00268 } // findLayer 00269 00270 00271 00272 00273 void QgsProjectBadLayerGuiHandler::findLayers( QString const & fileFilters, QList<QDomNode> const & layerNodes ) 00274 { 00275 00276 for ( QList<QDomNode>::const_iterator i = layerNodes.begin(); 00277 i != layerNodes.end(); 00278 ++i ) 00279 { 00280 if ( findLayer( fileFilters, *i ) ) 00281 { 00282 // If findLayer returns true, the user hit Cancel All button 00283 break; 00284 } 00285 } 00286 00287 } // findLayers 00288