From 61e196b525a760148dfcf0e05f5e677addec8e5d Mon Sep 17 00:00:00 2001 From: mcoletti Date: Sat, 21 Feb 2004 06:27:11 +0000 Subject: [PATCH] - fixed command line raster layer bug main.cpp : - greatly simplified main() - now will try to load a command line argument first as raster, then vector; if it succeeds at the first, it won't try the second qgisapp.{h,cpp} : - added addLayer(QFileInfo const &) [0] - added addRasterLayer(QFileInfo const &) [0] - do a little better checking for null pointers and freeing up resources when an error occurs Notes: Also, multiple rasters and vectors should be able to be specified on the command line without problems. [0] These will return true if successfully loaded the given file, otherwise false. git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@878 c8812cc2-4d05-0410-92ff-de0c093fc19c --- src/main.cpp | 52 +++--- src/qgisapp.cpp | 420 ++++++++++++++++++++++++++++++++++++++---------- src/qgisapp.h | 66 +++++++- 3 files changed, 411 insertions(+), 127 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 07808a334ee..bafeb424387 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,13 +28,10 @@ int main(int argc, char *argv[]) { - QString myArgString; - QFile myQFile; - QStringList myFileStringList; - bool myFileExistsFlag; QApplication a(argc, argv); // a.setFont(QFont("helvetica", 11)); + QTranslator tor(0); // set the location where your .qm files are in load() below as the last parameter instead of "." // for development, use "/" to use the english original as @@ -56,41 +53,34 @@ int main(int argc, char *argv[]) a.setMainWidget(qgis); qgis->show(); + // // autoload any filenames that were passed in on the command line // - for (int myIteratorInt = 1; myIteratorInt < argc; myIteratorInt++) + for (int i = 1; i < argc; i++) { #ifdef QGISDEBUG - printf("%d: %s\n", myIteratorInt, argv[myIteratorInt]); + printf("%d: %s\n", i, argv[i]); #endif - myQFile.setName(argv[myIteratorInt]); - myFileExistsFlag = myQFile.open(IO_ReadOnly); - myQFile.close(); - if (myFileExistsFlag) - { + // try to add all these layers - any unsupported file types will + // be refected automatically + if ( qgis->addRasterLayer(argv[i]) ) + { + // NOP + continue; + } + else if ( qgis->addLayer(argv[i]) ) + { + // NOP + continue; + } + else + { + // XXX should have complaint here about file not being valid #ifdef QGISDEBUG - printf("OK\n"); + std::cerr << argv[i] << " is not a recognized file\n"; #endif - myArgString = argv[myIteratorInt]; -#ifdef QGISDEBUG - printf("Layer count: %d\n", myFileStringList.count()); -#endif - myFileStringList.append(myArgString); - - } - } -#ifdef QGISDEBUG - printf("rCount: %d\n", myFileStringList.count()); -#endif - if (!myFileStringList.isEmpty()) - { -#ifdef QGISDEBUG - printf("Loading vector files...\n"); -#endif - //try to add all these layers - any unsupported file types will be refected automatically - qgis->addRasterLayer(myFileStringList); - qgis->addLayer(myFileStringList); + } } a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); diff --git a/src/qgisapp.cpp b/src/qgisapp.cpp index 5d037fda424..e715b2e2032 100644 --- a/src/qgisapp.cpp +++ b/src/qgisapp.cpp @@ -20,40 +20,39 @@ #include -#include #include -#include +#include +#include #include #include +#include #include -#include -#include #include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -538,7 +537,10 @@ static void openFilesRememberingFilter_(QString const &filterName, QString const /** - This method prompts the user for a list of vector filenames with a dialog. + This method prompts the user for a list of vector filenames with a dialog. + + @todo XXX I'd really like to return false, but can't because this + XXX is for a slot that was defined void; need to fix. */ void QgisApp::addLayer() { @@ -555,6 +557,7 @@ void QgisApp::addLayer() #ifdef QGISDEBUG qDebug("unable to get OGR registry"); #endif + return; } else { mapCanvas->freeze(); @@ -566,8 +569,10 @@ void QgisApp::addLayer() { // no files were selected, so just bail mapCanvas->freeze(false); + return; } + addLayer(selectedFiles); } } // QgisApp::addLayer() @@ -575,70 +580,207 @@ void QgisApp::addLayer() - -/** \brief overloaded vesion of the above method that takes a list of - * filenames instead of prompting user with a dialog. */ -void QgisApp::addLayer(QStringList const &theLayerQStringList) +bool QgisApp::addLayer(QFileInfo const & vectorFile) { // check to see if we have an ogr provider available QString pOgr = providerRegistry->library("ogr"); - if (pOgr.length() > 0) + + if ( pOgr.isEmpty() ) + { + QMessageBox::critical(this, + tr("No OGR Provider"), + tr("No OGR data provider was found in the QGIS lib directory")); + return false; + } + + // let the user know we're going to possibly be taking a while + QApplication::setOverrideCursor(Qt::WaitCursor); + + mapCanvas->freeze(); // XXX why do we do this? + + // create the layer + + QgsVectorLayer *layer = new QgsVectorLayer(vectorFile.filePath(), + vectorFile.baseName(), + "ogr"); + Q_CHECK_PTR( layer ); + + if ( ! layer ) + { + mapCanvas->freeze(false); + QApplication::restoreOverrideCursor(); + + // XXX insert meaningful whine to the user here + return false; + } + + if (layer->isValid()) + { + // init the context menu so it can connect to slots + // in main app + + layer->initContextMenu(this); + + //add single symbol renderer as default + QgsSingleSymRenderer *renderer = new QgsSingleSymRenderer(); + + Q_CHECK_PTR( renderer ); + + if ( ! renderer ) + { + mapCanvas->freeze(false); + QApplication::restoreOverrideCursor(); + + // XXX should we also delete the layer? + + // XXX insert meaningful whine to the user here + return false; + } + + layer->setRenderer(renderer); + renderer->initializeSymbology(layer); + mapCanvas->addLayer(layer); + projectIsDirty = true; + + } else + { + QString msg = vectorFile.baseName() + " "; + msg += tr("is not a valid or recognized data source"); + QMessageBox::critical(this, tr("Invalid Data Source"), msg); + + // since the layer is bad, stomp on it + delete layer; + + mapCanvas->freeze(false); + QApplication::restoreOverrideCursor(); + + return false; + } + + mapCanvas->freeze(false); + mapLegend->update(); + qApp->processEvents(); // XXX why does this need to be called manually? + mapCanvas->render2(); // XXX eh, wot? + + QApplication::restoreOverrideCursor(); + + statusBar()->message(mapCanvas->extent().stringRep()); + + return true; + +} // QgisApp::addLayer() + + + + + +/** \brief overloaded vesion of the above method that takes a list of + * filenames instead of prompting user with a dialog. + + XXX yah know, this could be changed to just iteratively call the above + + */ +bool QgisApp::addLayer(QStringList const &theLayerQStringList) +{ + // check to see if we have an ogr provider available + QString pOgr = providerRegistry->library("ogr"); + + if ( pOgr.isEmpty() ) + { + QMessageBox::critical(this, + tr("No OGR Provider"), + tr("No OGR data provider was found in the QGIS lib directory")); + return false; + } + else { mapCanvas->freeze(); + QApplication::setOverrideCursor(Qt::WaitCursor); - QStringList::ConstIterator it = theLayerQStringList.begin(); - while (it != theLayerQStringList.end()) + + + for ( QStringList::ConstIterator it = theLayerQStringList.begin(); + it != theLayerQStringList.end(); + ++it ) { - if (true) - { - // if (isValidVectorFileName(*it)) { - - QFileInfo fi(*it); - QString base = fi.baseName(); + QFileInfo fi(*it); + QString base = fi.baseName(); - // create the layer + // create the layer - //dp QgsShapeFileLayer *lyr = new QgsShapeFileLayer(*it, base); - QgsVectorLayer *lyr = new QgsVectorLayer(*it, base, "ogr"); + QgsVectorLayer *layer = new QgsVectorLayer(*it, base, "ogr"); + + Q_CHECK_PTR( layer ); + + if ( ! layer ) + { + mapCanvas->freeze(false); + QApplication::restoreOverrideCursor(); + + // XXX insert meaningful whine to the user here + return false; + } + + if (layer->isValid()) + { + // init the context menu so it can connect to slots + // in main app + + layer->initContextMenu(this); + + //add single symbol renderer as default + QgsSingleSymRenderer *renderer = new QgsSingleSymRenderer(); + + Q_CHECK_PTR( renderer ); + + if ( ! renderer ) + { + mapCanvas->freeze(false); + QApplication::restoreOverrideCursor(); + + // XXX insert meaningful whine to the user here + return false; + } + + layer->setRenderer(renderer); + renderer->initializeSymbology(layer); + mapCanvas->addLayer(layer); + projectIsDirty = true; + } else + { + QString msg = *it + " "; + msg += tr("is not a valid or recognized data source"); + QMessageBox::critical(this, tr("Invalid Data Source"), msg); + + // since the layer is bad, stomp on it + delete layer; + + // XXX should we return false here, or just grind through + // XXX the remaining arguments? + } - if (lyr->isValid()) - { - // init the context menu so it can connect to slots in main app - lyr->initContextMenu(this); - //add single symbol renderer as default - QgsSingleSymRenderer *renderer = new QgsSingleSymRenderer(); - lyr->setRenderer(renderer); - renderer->initializeSymbology(lyr); - mapCanvas->addLayer(lyr); - projectIsDirty = true; - } else - { - QString msg = *it + " "; - msg += tr("is not a valid or recognized data source"); - QMessageBox::critical(this, tr("Invalid Data Source"), msg); - } - } //end of isValidVectorFileName check - ++it; } + //qApp->processEvents(); // update legend /*! \todo Need legend scrollview and legenditem classes */ // draw the map mapLegend->update(); - qApp->processEvents(); + qApp->processEvents(); // XXX why does this need to be called manually? mapCanvas->freeze(false); mapCanvas->render2(); QApplication::restoreOverrideCursor(); statusBar()->message(mapCanvas->extent().stringRep()); - } else - { - QMessageBox::critical(this, tr("No OGR Provider"), tr("No OGR data provider was found in the QGIS lib directory")); - } + } + + return true; + +} // QgisApp::addLayer() + -} /** @@ -857,7 +999,8 @@ static void buildSupportedRasterFileFilter_(QString & fileFilters) - +/** @todo XXX I'd *really* like to return, ya know, _false_. + */ void QgisApp::addRasterLayer() { mapCanvas->freeze(); @@ -873,17 +1016,86 @@ void QgisApp::addRasterLayer() if (selectedFiles.isEmpty()) { // no files were selected, so just bail - return; + return; } - addRasterLayer(selectedFiles); + addRasterLayer(selectedFiles); } // QgisApp::addRasterLayer() -void QgisApp::addRasterLayer(QStringList const &theFileNameQStringList) + +bool QgisApp::addRasterLayer(QFileInfo const & rasterFile) +{ + // let the user know we're going to possibly be taking a while + QApplication::setOverrideCursor(Qt::WaitCursor); + + mapCanvas->freeze(); // XXX why do we do this? + + // XXX ya know QgsRasterLayer can snip out the basename on its own; + // XXX why do we have to pass it in for it? + QgsRasterLayer *layer = + new QgsRasterLayer(rasterFile.filePath(), rasterFile.baseName()); + + Q_CHECK_PTR( layer ); + + if ( ! layer ) + { + mapCanvas->freeze(false); + QApplication::restoreOverrideCursor(); + + // XXX insert meaningful whine to the user here; although be + // XXX mindful that a null layer may mean exhausted memory resources + return false; + } + + if (layer->isValid()) + { + // XXX doesn't the mapCanvas->addLayer() do this? + QObject::connect(layer, + SIGNAL(repaintRequested()), + mapCanvas, + SLOT(refresh())); + + // add it to the mapcanvas collection + mapCanvas->addLayer(layer); + projectIsDirty = true; + + // init the context menu so it can connect to slots in main app + layer->initContextMenu(this); + } else + { + QString msg(rasterFile.baseName() + " is not a valid or recognized raster data source"); + QMessageBox::critical(this, "Invalid Data Source", msg); + + delete layer; + + mapCanvas->freeze(false); + QApplication::restoreOverrideCursor(); + + return false; + } + + + mapLegend->update(); + qApp->processEvents(); + mapCanvas->freeze(false); + mapCanvas->render2(); + QApplication::restoreOverrideCursor(); + statusBar()->message(mapCanvas->extent().stringRep()); + + return true; + +} // QgisApp::addRasterLayer + + + +/** + @todo XXX ya know, this could be changed to iteratively call the above +*/ +bool QgisApp::addRasterLayer(QStringList const &theFileNameQStringList) { if (theFileNameQStringList.empty()) { @@ -891,31 +1103,48 @@ void QgisApp::addRasterLayer(QStringList const &theFileNameQStringList) // allow mapCanvas to handle events // first mapCanvas->freeze(false); - return; + return false; } else { mapCanvas->freeze(); } QApplication::setOverrideCursor(Qt::WaitCursor); - for (QStringList::ConstIterator myIterator = theFileNameQStringList.begin(); myIterator != theFileNameQStringList.end(); + + for (QStringList::ConstIterator myIterator = theFileNameQStringList.begin(); + myIterator != theFileNameQStringList.end(); ++myIterator) { if (isValidRasterFileName(*myIterator)) { QFileInfo myFileInfo(*myIterator); - QString myDirNameQString = myFileInfo.dirPath(); //get the directory the .adf file was in + // get the directory the .adf file was in + QString myDirNameQString = myFileInfo.dirPath(); QString myBaseNameQString = myFileInfo.baseName(); - //only allow one copy of a ai grid file to be loaded at a time to - //prevent the user selecting all adfs in 1 dir which actually represent 1 coverate, + //only allow one copy of a ai grid file to be loaded at a + //time to prevent the user selecting all adfs in 1 dir which + //actually represent 1 coverate, // create the layer QgsRasterLayer *layer = new QgsRasterLayer(*myIterator, myBaseNameQString); - QObject::connect(layer, SIGNAL(repaintRequested()), mapCanvas, SLOT(refresh())); + Q_CHECK_PTR( layer ); + if ( ! layer ) + { + mapCanvas->freeze(false); + QApplication::restoreOverrideCursor(); + + // XXX insert meaningful whine to the user here + return false; + } if (layer->isValid()) { - // add it to the mapcanvas collection + QObject::connect(layer, + SIGNAL(repaintRequested()), + mapCanvas, + SLOT(refresh())); + + // add it to the mapcanvas collection mapCanvas->addLayer(layer); projectIsDirty = true; // init the context menu so it can connect to slots in main app @@ -925,17 +1154,25 @@ void QgisApp::addRasterLayer(QStringList const &theFileNameQStringList) { QString msg(*myIterator + " is not a valid or recognized raster data source"); QMessageBox::critical(this, "Invalid Data Source", msg); + + delete layer; + + // XXX should we return false here, or just grind through + // XXX the remaining arguments? } - //only allow one copy of a ai grid file to be loaded at a time to - //prevent the user selecting all adfs in 1 dir which actually represent 1 coverate, + //only allow one copy of a ai grid file to be loaded at a + //time to prevent the user selecting all adfs in 1 dir which + //actually represent 1 coverate, + if (myBaseNameQString.lower().endsWith(".adf")) { break; } - } //end of isValidRasterFileName check + } } + mapLegend->update(); qApp->processEvents(); @@ -948,8 +1185,15 @@ void QgisApp::addRasterLayer(QStringList const &theFileNameQStringList) statusBar()->message(mapCanvas->extent().stringRep()); + return true; + } // QgisApp::addRasterLayer() + + + + + /** This helper checks to see whether the filename appears to be a valid raster file name */ bool QgisApp::isValidRasterFileName(QString theFileNameQString) { @@ -1015,25 +1259,25 @@ void QgisApp::addDatabaseLayer() { // create the layer - //qWarning("creating lyr"); - QgsVectorLayer *lyr = new QgsVectorLayer(connInfo + " table=" + *it, *it, "postgres"); - if (lyr->isValid()) + //qWarning("creating layer"); + QgsVectorLayer *layer = new QgsVectorLayer(connInfo + " table=" + *it, *it, "postgres"); + if (layer->isValid()) { // init the context menu so it can connect to slots in main app - lyr->initContextMenu(this); + layer->initContextMenu(this); // give it a random color QgsSingleSymRenderer *renderer = new QgsSingleSymRenderer(); //add single symbol renderer as default - lyr->setRenderer(renderer); - renderer->initializeSymbology(lyr); + layer->setRenderer(renderer); + renderer->initializeSymbology(layer); // add it to the mapcanvas collection - mapCanvas->addLayer(lyr); + mapCanvas->addLayer(layer); projectIsDirty = true; } else { std::cerr << *it << " is an invalid layer - not loaded" << std::endl; QMessageBox::critical(this, tr("Invalid Layer"), tr("%1 is an invalid layer and cannot be loaded.").arg(*it)); - delete lyr; + delete layer; } //qWarning("incrementing iterator"); ++it; @@ -1227,10 +1471,10 @@ void QgisApp::attributeTable() QListViewItem *li = mapLegend->currentItem(); if (li) { - QgsMapLayer *lyr = ((QgsLegendItem *) li)->layer(); - if (lyr) + QgsMapLayer *layer = ((QgsLegendItem *) li)->layer(); + if (layer) { - lyr->table(); + layer->table(); } else { diff --git a/src/qgisapp.h b/src/qgisapp.h index d32a602cf96..b82a700c244 100644 --- a/src/qgisapp.h +++ b/src/qgisapp.h @@ -30,6 +30,7 @@ class QVBox; class QCursor; class QListView; class QListViewItem; +class QFileInfo; class QgsMapLayer; class QSocket; class QgsProviderRegistry; @@ -40,7 +41,7 @@ class QgsMapCanvas; /*! \class QgisApp * \brief Main window for the Qgis application */ -class QgisApp:public QgisAppBase +class QgisApp : public QgisAppBase { Q_OBJECT public: //! Constructor @@ -49,18 +50,67 @@ class QgisApp:public QgisAppBase ~QgisApp(); public: QgisIface *getInterface(); + + /** + @todo XXX what the heck is this? + */ int getInt(); + void addVectorLayer(QString vectorLayerPath, QString baseName, QString providerKey); /** \brief overloaded vesion of the privat addLayer method that takes a list of - * filenames instead of prompting user with a dialog. */ - void addLayer(QStringList const & theLayerQStringList); - /** \brief overloaded vesion of the privat addLRasterayer method that takes a list of - * filenames instead of prompting user with a dialog. */ - void addRasterLayer(QStringList const & theLayerQStringList); + * filenames instead of prompting user with a dialog. + + @returns true if successfully added layer + + @note + + This should be deprecated because it's possible to have a + heterogeneous set of files; i.e., a mix of raster and vector. + It's much better to try to just open one file at a time. + + */ + bool addLayer(QStringList const & theLayerQStringList); + + /** open a vector layer for the given file + + @returns false if unable to open a raster layer for rasterFile + + @note + + This is essentially a simplified version of the above + */ + bool addLayer(QFileInfo const & vectorFile); + + + /** overloaded vesion of the private addRasterLayer() + + Method that takes a list of filenames instead of prompting + user with a dialog. + + @returns true if successfully added layer(s) + + @note + + This should be deprecated because it's possible to have a + heterogeneous set of files; i.e., a mix of raster and vector. + It's much better to try to just open one file at a time. + + */ + bool addRasterLayer(QStringList const & theLayerQStringList); + + + /** open a raster layer for the given file + + @returns false if unable to open a raster layer for rasterFile + + @note + + This is essentially a simplified version of the above + */ + bool addRasterLayer(QFileInfo const & rasterFile); private: - //private: - //public slots: + //! Add a vector layer to the map void addLayer(); //! Add a raster layer to the map