124 changes: 124 additions & 0 deletions src/core/qgserror.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/***************************************************************************
qgserror.h - Error container
-------------------
begin : October 2012
copyright : (C) 2012 Radim Blazek
email : radim dot blazek at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSERROR_H
#define QGSERROR_H

#include <QString>
#include <QList>

// Macro to create Error message including info about where it was created.
#define QGS_ERROR_MESSAGE(message, tag) QgsErrorMessage(QString(message),QString(tag), QString(__FILE__), QString(__FUNCTION__), __LINE__)

/** \ingroup core
* QgsErrorMessage represents single error message.
*/
class CORE_EXPORT QgsErrorMessage
{
public:
/** Format */
enum Format
{
Text, // Plain text
Html
};

QgsErrorMessage() {}

/** Constructor.
* @param theMessage error message string
* @param theTag error label, for example GDAL, GDAL Provider, Raster layer
* @param theFile the file where error was created
* @param theFunction the function where error was created
* @param theLine the line where error was created
*/
QgsErrorMessage ( const QString & theMessage, const QString & theTag = QString::null, const QString & theFile = QString::null, const QString & theFunction = QString::null, int theLine = 0 );

QString message() const { return mMessage; }
QString tag() const { return mTag; }
QString file() const { return mFile; }
QString function() const { return mFunction; }
int line() const { return mLine; }

private:
/** Error messages */
QString mMessage;

/** Short description */
QString mTag;

/** Detailed debug info */
QString mFile;
QString mFunction;
int mLine;

/* Message format */
Format mFormat;
};

/** \ingroup core
* QgsError is container for error messages (report). It may contain chain
* (sort of traceback) of error messages (e.g. GDAL - provider - layer).
* Higher level messages are appended at the end.
*/
class CORE_EXPORT QgsError
{
public:

QgsError() {}

/** Constructor with single message.
* @param theMessage error message
* @param theTag short description, e.g. GDAL, Provider, Layer
*/
QgsError ( const QString & theMessage, const QString & theTag );

/** Append new error message.
* @param theMessage error message string
* @param theTag error label, for example GDAL, GDAL Provider, Raster layer
*/
void append ( const QString & theMessage, const QString & theTag );

/** Append new error message.
* @param theMessage error message
*/
void append ( const QgsErrorMessage & theMessage );

/** Test if any error is set.
* @return true if contains error
*/
bool isEmpty() const { return mMessageList.isEmpty(); }

/** Full error messages description
* @param theFormat output format
* @return error report
*/
QString message( QgsErrorMessage::Format theFormat = QgsErrorMessage::Html ) const;

/** Short error descriprion, usually the first error in chain, the real error.
* @return error description
*/
QString summary() const;

/** Clear error messages */
void clear() { mMessageList.clear(); }

private:
/** List of messages */
QList<QgsErrorMessage> mMessageList;
};

#endif
15 changes: 15 additions & 0 deletions src/core/qgsmaplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <QDomNode>

#include "qgis.h"
#include "qgserror.h"
#include "qgsrectangle.h"

class QgsRenderContext;
Expand Down Expand Up @@ -218,6 +219,12 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
virtual QString lastError();

/** Get current status error. This error describes some principal problem
* for which layer cannot work and thus is not valid. It is not last error
* after accessing data by draw() etc.
*/
virtual QgsError error() const { return mError; }

/** Returns layer's spatial reference system
@note This was introduced in QGIS 1.4
*/
Expand Down Expand Up @@ -419,6 +426,11 @@ class CORE_EXPORT QgsMapLayer : public QObject
/** debugging member - invoked when a connect() is made to this object */
void connectNotify( const char * signal );

/** Add error message */
void appendError( const QgsErrorMessage & theMessage ) { mError.append( theMessage );}
/** Set error message */
void setError( const QgsError & theError ) { mError = theError;}

/** Transparency level for this layer should be 0-255 (255 being opaque) */
unsigned int mTransparencyLevel;

Expand All @@ -439,6 +451,9 @@ class CORE_EXPORT QgsMapLayer : public QObject
/**Description of the layer*/
QString mAbstract;

/** \brief Error */
QgsError mError;

private:
/** layer's spatial reference system.
private to make sure setCrs must be used and layerCrsChanged() is emitted */
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsproviderregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ void * QgsProviderRegistry::function( QString const & providerKey,
delete myLib;
return ptr;
}
QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
delete myLib;
return 0;
}
Expand All @@ -467,6 +468,7 @@ QLibrary *QgsProviderRegistry::providerLibrary( QString const & providerKey ) co
{
return myLib;
}
QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
delete myLib;
return 0;
}
Expand Down
7 changes: 5 additions & 2 deletions src/core/raster/qgsrasterchecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* *
***************************************************************************/

#include "qgsproviderregistry.h"
#include "qgsrasterchecker.h"
#include "qgsrasterdataprovider.h"
#include "qgsrasterlayer.h"
Expand Down Expand Up @@ -43,14 +44,16 @@ bool QgsRasterChecker::runTest( QString theVerifiedKey, QString theVerifiedUri,
bool ok = true;
mReport += "\n\n";

QgsRasterDataProvider* verifiedProvider = QgsRasterLayer::loadProvider( theVerifiedKey, theVerifiedUri );
//QgsRasterDataProvider* verifiedProvider = QgsRasterLayer::loadProvider( theVerifiedKey, theVerifiedUri );
QgsRasterDataProvider* verifiedProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( theVerifiedKey, theVerifiedUri );
if ( !verifiedProvider || !verifiedProvider->isValid() )
{
error( QString( "Cannot load provider %1 with URI: %2" ).arg( theVerifiedKey ).arg( theVerifiedUri ), mReport );
ok = false;
}

QgsRasterDataProvider* expectedProvider = QgsRasterLayer::loadProvider( theExpectedKey, theExpectedUri );
//QgsRasterDataProvider* expectedProvider = QgsRasterLayer::loadProvider( theExpectedKey, theExpectedUri );
QgsRasterDataProvider* expectedProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( theExpectedKey, theExpectedUri );
if ( !expectedProvider || !expectedProvider->isValid() )
{
error( QString( "Cannot load provider %1 with URI: %2" ).arg( theExpectedKey ).arg( theExpectedUri ), mReport );
Expand Down
26 changes: 1 addition & 25 deletions src/core/raster/qgsrasterdataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "qgslogger.h"
#include "qgsrectangle.h"
#include "qgsdataprovider.h"
#include "qgserror.h"
#include "qgsrasterinterface.h"
#include "qgscolorrampshader.h"
#include "qgsrasterpyramid.h"
Expand Down Expand Up @@ -144,31 +145,6 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
/* It makes no sense to set input on provider */
bool setInput( QgsRasterInterface* input ) { Q_UNUSED( input ); return false; }

/**
* Add the list of WMS layer names to be rendered by this server
*/
virtual void addLayers( const QStringList & layers,
const QStringList & styles = QStringList() ) = 0;

//! get raster image encodings supported by (e.g.) the WMS Server, expressed as MIME types
virtual QStringList supportedImageEncodings() = 0;

/**
* Get the image encoding (as a MIME type) used in the transfer from (e.g.) the WMS server
*/
virtual QString imageEncoding() const = 0;

/**
* Set the image encoding (as a MIME type) used in the transfer from (e.g.) the WMS server
*/
virtual void setImageEncoding( const QString & mimeType ) = 0;

/**
* Set the image projection (in WMS CRS format) used in the transfer from (e.g.) the WMS server
*/
virtual void setImageCrs( const QString & crs ) = 0;


// TODO: Document this better.
/** \brief Renders the layer as an image
*/
Expand Down
9 changes: 6 additions & 3 deletions src/core/raster/qgsrasterfilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,8 @@ void QgsRasterFileWriter::buildPyramids( const QString& filename )
void QgsRasterFileWriter::buildPyramids( const QString& filename )
{
// open new dataProvider so we can build pyramids with it
QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, filename );
//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, filename );
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, filename );
if ( !destProvider )
{
return;
Expand Down Expand Up @@ -834,7 +835,8 @@ QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider( const QgsRectang
QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );

QString outputFile = outputUrl + "/" + QString::number( fileIndex );
QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, outputFile );
//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, outputFile );
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, outputFile );
if ( !destProvider )
{
return 0;
Expand Down Expand Up @@ -869,7 +871,8 @@ QgsRasterDataProvider* QgsRasterFileWriter::initOutput( int nCols, int nRows, co
}
else
{
QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, mOutputUrl );
//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, mOutputUrl );
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, mOutputUrl );
if ( !destProvider )
{
return 0;
Expand Down
123 changes: 21 additions & 102 deletions src/core/raster/qgsrasterlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ typedef bool isvalidrasterfilename_t( QString const & theFileNameQString, QStrin
// doubles can take for the current system. (Yes, 20 was arbitrary.)
#define TINY_VALUE std::numeric_limits<double>::epsilon() * 20

#define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")

const double QgsRasterLayer::CUMULATIVE_CUT_LOWER = 0.02;
const double QgsRasterLayer::CUMULATIVE_CUT_UPPER = 0.98;
const double QgsRasterLayer::SAMPLE_SIZE = 250000;
Expand Down Expand Up @@ -121,6 +123,7 @@ QgsRasterLayer::QgsRasterLayer(
// TODO, call constructor with provider key
init();
setDataProvider( "gdal" );
if ( !mValid ) return;

bool defaultLoadedFlag = false;
if ( mValid && loadDefaultStyleFlag )
Expand Down Expand Up @@ -157,6 +160,7 @@ QgsRasterLayer::QgsRasterLayer( const QString & uri,
QgsDebugMsg( "Entered" );
init();
setDataProvider( providerKey );
if ( !mValid ) return;

// load default style
bool defaultLoadedFlag = false;
Expand Down Expand Up @@ -189,6 +193,7 @@ QgsRasterLayer::QgsRasterLayer( const QString & uri,
QgsRasterLayer::~QgsRasterLayer()
{
mValid = false;
//delete mDataProvider; // deleted by pipe
}

//////////////////////////////////////////////////////////
Expand All @@ -207,44 +212,29 @@ QgsRasterLayer::~QgsRasterLayer()
void QgsRasterLayer::buildSupportedRasterFileFilter( QString & theFileFiltersString )
{
QgsDebugMsg( "Entered" );
QLibrary* myLib = QgsRasterLayer::loadProviderLibrary( "gdal" );
if ( !myLib )
{
QgsDebugMsg( "Could not load gdal provider library" );
return;
}
buildsupportedrasterfilefilter_t *pBuild = ( buildsupportedrasterfilefilter_t * ) cast_to_fptr( myLib->resolve( "buildSupportedRasterFileFilter" ) );
buildsupportedrasterfilefilter_t *pBuild = ( buildsupportedrasterfilefilter_t * ) cast_to_fptr( QgsProviderRegistry::instance()->function( "gdal", "buildSupportedRasterFileFilter" ) );
if ( ! pBuild )
{
QgsDebugMsg( "Could not resolve buildSupportedRasterFileFilter in gdal provider library" );
QgsDebugMsg( "Could get buildSupportedRasterFileFilter in gdal provider library" );
return;
}

pBuild( theFileFiltersString );
delete myLib;
}

/**
* This helper checks to see whether the file name appears to be a valid raster file name
*/
bool QgsRasterLayer::isValidRasterFileName( QString const & theFileNameQString, QString & retErrMsg )
{

QLibrary* myLib = QgsRasterLayer::loadProviderLibrary( "gdal" );
if ( !myLib )
{
QgsDebugMsg( "Could not load gdal provider library" );
return false;
}
isvalidrasterfilename_t *pValid = ( isvalidrasterfilename_t * ) cast_to_fptr( myLib->resolve( "isValidRasterFileName" ) );
isvalidrasterfilename_t *pValid = ( isvalidrasterfilename_t * ) cast_to_fptr( QgsProviderRegistry::instance()->function( "gdal", "isValidRasterFileName" ) );
if ( ! pValid )
{
QgsDebugMsg( "Could not resolve isValidRasterFileName in gdal provider library" );
return false;
}

bool myIsValid = pValid( theFileNameQString, retErrMsg );
delete myLib;
return myIsValid;
}

Expand Down Expand Up @@ -1587,96 +1577,18 @@ void QgsRasterLayer::init()
mLastViewPort.drawableAreaYDim = 0;
}

QLibrary* QgsRasterLayer::loadProviderLibrary( QString theProviderKey )
{
QgsDebugMsg( "theProviderKey = " + theProviderKey );
// load the plugin
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
QString myLibPath = pReg->library( theProviderKey );
QgsDebugMsg( "myLibPath = " + myLibPath );

#ifdef TESTPROVIDERLIB
const char *cOgrLib = ( const char * ) myLibPath;
// test code to help debug provider loading problems
// void *handle = dlopen(cOgrLib, RTLD_LAZY);
void *handle = dlopen( cOgrLib, RTLD_LAZY | RTLD_GLOBAL );
if ( !handle )
{
QgsLogger::warning( "Error in dlopen: " );
}
else
{
QgsDebugMsg( "dlopen suceeded" );
dlclose( handle );
}

#endif

// load the data provider
QLibrary* myLib = new QLibrary( myLibPath );

QgsDebugMsg( "Library name is " + myLib->fileName() );
bool loaded = myLib->load();

if ( !loaded )
{
QgsMessageLog::logMessage( tr( "Failed to load provider %1 (Reason: %2)" ).arg( myLib->fileName() ).arg( myLib->errorString() ), tr( "Raster" ) );
return NULL;
}
QgsDebugMsg( "Loaded data provider library" );
return myLib;
}

// This code should be shared also by vector layer -> move it to QgsMapLayer
QgsRasterDataProvider* QgsRasterLayer::loadProvider( QString theProviderKey, QString theDataSource )
void QgsRasterLayer::setDataProvider( QString const & provider )
{
QgsDebugMsg( "Entered" );
QLibrary* myLib = QgsRasterLayer::loadProviderLibrary( theProviderKey );
QgsDebugMsg( "Library loaded" );
if ( !myLib )
{
QgsDebugMsg( "myLib is NULL" );
return NULL;
}

QgsDebugMsg( "Attempting to resolve the classFactory function" );
classFactoryFunction_t * classFactory = ( classFactoryFunction_t * ) cast_to_fptr( myLib->resolve( "classFactory" ) );
mValid = false; // assume the layer is invalid until we determine otherwise

if ( !classFactory )
{
QgsMessageLog::logMessage( tr( "Cannot resolve the classFactory function" ), tr( "Raster" ) );
return NULL;
}
QgsDebugMsg( "Getting pointer to a mDataProvider object from the library" );
//XXX - This was a dynamic cast but that kills the Windows
// version big-time with an abnormal termination error
// mDataProvider = (QgsRasterDataProvider*)(classFactory((const
// char*)(dataSource.utf8())));

// Copied from qgsproviderregistry in preference to the above.
QgsRasterDataProvider* myDataProvider = ( QgsRasterDataProvider* )( *classFactory )( &theDataSource );

if ( !myDataProvider )
{
QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
return NULL;
}
QgsDebugMsg( "Data driver created" );
return myDataProvider;
}
mPipe.remove( mDataProvider ); // deletes if exists
mDataProvider = 0;

/** Copied from QgsVectorLayer::setDataProvider
* TODO: Make it work in the raster environment
*/
void QgsRasterLayer::setDataProvider( QString const & provider )
{
QgsDebugMsg( "Entered" );
// XXX should I check for and possibly delete any pre-existing providers?
// XXX How often will that scenario occur?

mProviderKey = provider;
mValid = false; // assume the layer is invalid until we determine otherwise

// set the layer name (uppercase first character)
if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
{
Expand All @@ -1685,13 +1597,19 @@ void QgsRasterLayer::setDataProvider( QString const & provider )

mBandCount = 0;

mDataProvider = QgsRasterLayer::loadProvider( mProviderKey, mDataSource );
mDataProvider = ( QgsRasterDataProvider* )QgsProviderRegistry::instance()->provider( mProviderKey, mDataSource );
if ( !mDataProvider )
{
//QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
return;
}
QgsDebugMsg( "Data provider created" );

if ( !mDataProvider->isValid() )
{
setError( mDataProvider->error() );
appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2" ).arg( mProviderKey ).arg( mDataSource ) ) );
return;
}
mPipe.set( mDataProvider );
Expand Down Expand Up @@ -2619,7 +2537,7 @@ bool QgsRasterLayer::readXml( const QDomNode& layer_node )
}

setDataProvider( mProviderKey );

if ( !mValid ) return false;

QString theError;
bool res = readSymbology( layer_node, theError );
Expand All @@ -2644,6 +2562,7 @@ bool QgsRasterLayer::readXml( const QDomNode& layer_node )
closeDataProvider();
init();
setDataProvider( mProviderKey );
if ( !mValid ) return false;
}
}

Expand Down
4 changes: 0 additions & 4 deletions src/core/raster/qgsrasterlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,6 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** [ data provider interface ] Set the data provider */
void setDataProvider( const QString & provider );

static QLibrary* loadProviderLibrary( QString theProviderKey );
static QgsRasterDataProvider* loadProvider( QString theProviderKey, QString theDataSource = 0 );


/** \brief Accessor for blue band name mapping */
QString blueBandName() const { return mBlueBandName; }

Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ qgsdetaileditemwidget.cpp
qgsdetaileditemdata.cpp
qgsdialog.cpp
qgsencodingfiledialog.cpp
qgserrordialog.cpp
qgsfiledropedit.cpp
qgsfieldvalidator.cpp
qgsformannotationitem.cpp
Expand Down Expand Up @@ -155,6 +156,7 @@ qgsdialog.h
qgslegendinterface.h
qgisinterface.h
qgsencodingfiledialog.h
qgserrordialog.h
qgsfieldvalidator.h
qgsformannotationitem.h
qgshtmlannotationitem.h
Expand Down
79 changes: 79 additions & 0 deletions src/gui/qgserrordialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/***************************************************************************
qgserrordialog.cpp - error description
-------------------
begin : October 2012
copyright : (C) October 2012 Radim Blazek
email : radim dot blazek at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgserrordialog.h"

#include <QMessageBox>
#include <QSettings>

QgsErrorDialog::QgsErrorDialog( const QgsError & theError, const QString & theTitle, QWidget *parent, Qt::WFlags fl )
: QDialog( parent, fl )
, mError( theError )
{
setupUi( this );
QString title = theTitle;
if ( title.isEmpty() ) title = tr("Error");
setWindowTitle( title );

// QMessageBox has static standardIcon( Icon icon ), but it is marked as obsolete
QMessageBox messageBox( QMessageBox::Critical, "", "" );
mIconLabel->setPixmap( messageBox.iconPixmap() );
mSummaryTextBrowser->setOpenExternalLinks ( true );
mDetailTextBrowser->setOpenExternalLinks ( true );
mDetailTextBrowser->hide();

QPalette p = palette();
p.setColor(QPalette::Base, Qt::transparent);
mSummaryTextBrowser->setPalette(p);

mDetailCheckBox->hide();

mSummaryTextBrowser->setText ( mError.summary() );
mDetailTextBrowser->setText( mError.message( QgsErrorMessage::Html ) );

resize( width(), 150);

QSettings settings;
Qt::CheckState state = (Qt::CheckState) settings.value( "/Error/dialog/detail", 0 ).toInt();
mDetailCheckBox->setCheckState( state );
if ( state == Qt::Checked ) on_mDetailPushButton_clicked();
}

QgsErrorDialog::~QgsErrorDialog()
{
}

void QgsErrorDialog::show ( const QgsError & theError, const QString & theTitle, QWidget *parent, Qt::WFlags fl )
{
QgsErrorDialog d( theError, theTitle, parent, fl );
d.exec();
}

void QgsErrorDialog::on_mDetailPushButton_clicked()
{
mSummaryTextBrowser->hide();
mDetailTextBrowser->show();
mDetailCheckBox->show();
mDetailPushButton->hide();
resize( width(), 400);
}

void QgsErrorDialog::on_mDetailCheckBox_stateChanged ( int state )
{
QSettings settings;
settings.setValue( "/Error/dialog/detail", state );
}

46 changes: 46 additions & 0 deletions src/gui/qgserrordialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/***************************************************************************
qgserrordialog.h - error dialog
-------------------
begin : October 2012
copyright : (C) October 2012 Radim Blazek
email : radim dot blazek at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSERRORDIALOG_H
#define QGSERRORDIALOG_H

#include <QDialog>

#include "ui_qgserrordialogbase.h"
#include "qgisgui.h"
#include "qgserror.h"

class GUI_EXPORT QgsErrorDialog: public QDialog, private Ui::QgsErrorDialogBase
{
Q_OBJECT
public:
QgsErrorDialog( const QgsError & theError, const QString & theTitle, QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags );
~QgsErrorDialog();

/** Show dialog with error
* @param theError error
*/
static void show ( const QgsError & theError, const QString & theTitle, QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags );

public slots:
void on_mDetailPushButton_clicked();
void on_mDetailCheckBox_stateChanged ( int state );

private:
QgsError mError;
};

#endif
8 changes: 3 additions & 5 deletions src/providers/gdal/qgsgdalprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "cpl_conv.h"
#include "cpl_string.h"

#define ERR(message) QGS_ERROR_MESSAGE(message,"GDAL provider")

static QString PROVIDER_KEY = "gdal";
static QString PROVIDER_DESCRIPTION = "GDAL provider";
Expand Down Expand Up @@ -134,8 +135,7 @@ QgsGdalProvider::QgsGdalProvider( QString const & uri )
if ( !mGdalBaseDataset )
{
QString msg = QString( "Cannot open GDAL dataset %1:\n%2" ).arg( dataSourceUri() ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
QgsDebugMsg( msg );
QgsMessageLog::logMessage( msg );
appendError( ERR( msg ) );
return;
}

Expand Down Expand Up @@ -538,7 +538,6 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
if ( err != CPLE_None )
{
QgsLogger::warning( "RasterIO error: " + QString::fromUtf8( CPLGetLastErrorMsg() ) );
QgsDebugMsg( "RasterIO error: " + QString::fromUtf8( CPLGetLastErrorMsg() ) );
QgsFree( tmpBlock );
return;
}
Expand Down Expand Up @@ -2223,8 +2222,7 @@ void QgsGdalProvider::initBaseDataset()
// if there are no subdatasets, then close the dataset
if ( mSubLayers.size() == 0 )
{
QMessageBox::warning( 0, QObject::tr( "Warning" ),
QObject::tr( "Cannot get GDAL raster band: %1" ).arg( msg ) );
appendError( ERR( tr( "Cannot get GDAL raster band: %1" ).arg( msg ) ) );

GDALDereferenceDataset( mGdalBaseDataset );
mGdalBaseDataset = NULL;
Expand Down
10 changes: 0 additions & 10 deletions src/providers/gdal/qgsgdalprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,6 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
*/
QString metadata();

// Following methods specific for WMS are not used at all in this provider and should be removed IMO from qgsdataprovider.h
void addLayers( QStringList const &layers, QStringList const &styles = QStringList() )
{ Q_UNUSED( layers ); Q_UNUSED( styles ); }
QStringList supportedImageEncodings() { return QStringList(); }
QString imageEncoding() const { return QString(); }
void setImageEncoding( QString const &mimeType )
{ Q_UNUSED( mimeType ); }
void setImageCrs( QString const &crs )
{ Q_UNUSED( crs ); }

/** \brief Returns the sublayers of this layer - Useful for providers that manage their own layers, such as WMS */
QStringList subLayers() const;
static QStringList subLayers( GDALDatasetH dataset );
Expand Down
21 changes: 15 additions & 6 deletions src/providers/grass/qgsgrassrasterprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,32 @@
#include <QFile>
#include <QHash>

#define ERR(message) QGS_ERROR_MESSAGE(message,"GRASS provider")

static QString PROVIDER_KEY = "grassraster";
static QString PROVIDER_DESCRIPTION = "GRASS raster provider";

QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
: QgsRasterDataProvider( uri ), mValid( true )
: QgsRasterDataProvider( uri ), mValid( false )
{
QgsDebugMsg( "QgsGrassRasterProvider: constructing with uri '" + uri + "'." );

mValid = false;
// Parse URI, it is the same like using GDAL, i.e. path to raster cellhd, i.e.
// /path/to/gisdbase/location/mapset/cellhd/map
QFileInfo fileInfo( uri );
mValid = fileInfo.exists(); // then we keep it valid forever
if ( !fileInfo.exists() ) // then we keep it valid forever
{
appendError( ERR( tr( "cellhd file %1 does not exist" ).arg( uri ) ) );
return;
}

mMapName = fileInfo.fileName();
QDir dir = fileInfo.dir();
QString element = dir.dirName();
if ( element != "cellhd" )
{
QMessageBox::warning( 0, QObject::tr( "Warning" ),
QObject::tr( "Groups not yet supported" ) + " (GRASS " + uri + ")" );

mValid = false;
appendError( ERR( tr( "Groups not yet supported" ) ) );
return;
}
dir.cdUp(); // skip cellhd
Expand Down Expand Up @@ -133,6 +138,7 @@ QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
{
mYBlockSize = mRows;
}
mValid = true;
QgsDebugMsg( "mYBlockSize = " + QString::number( mYBlockSize ) );
}

Expand Down Expand Up @@ -398,10 +404,13 @@ QgsCoordinateReferenceSystem QgsGrassRasterProvider::crs()

QgsRectangle QgsGrassRasterProvider::extent()
{
QgsDebugMsg( "Entered" );
// The extend can change of course so we get always fresh, to avoid running always the module
// we should save mExtent and mLastModified and check if the map was modified

mExtent = QgsGrass::extent( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );

QgsDebugMsg( "Extent got" );
return mExtent;
}

Expand Down
10 changes: 0 additions & 10 deletions src/providers/grass/qgsgrassrasterprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,16 +207,6 @@ class QgsGrassRasterProvider : public QgsRasterDataProvider
*/
QString metadata();

// Following methods specific for are not used at all in this provider and should be removed IMO from qgsdataprovider.h
void addLayers( QStringList const &layers, QStringList const &styles = QStringList() )
{ Q_UNUSED( layers ); Q_UNUSED( styles ); }
QStringList supportedImageEncodings() { return QStringList();}
QString imageEncoding() const { return QString(); }
void setImageEncoding( QString const &mimeType )
{ Q_UNUSED( mimeType ); }
void setImageCrs( QString const &crs )
{ Q_UNUSED( crs ); }

virtual QDateTime dataTimestamp() const;
private:

Expand Down
20 changes: 13 additions & 7 deletions src/providers/wcs/qgswcsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
#include "cpl_conv.h"
#include "cpl_string.h"

#define ERR(message) QGS_ERROR_MESSAGE(message,"WCS provider")
#define SRVERR(message) QGS_ERROR_MESSAGE(message,"WCS server")

static QString WCS_KEY = "wcs";
static QString WCS_DESCRIPTION = "OGC Web Coverage Service version 1.0/1.1 data provider";

Expand Down Expand Up @@ -117,15 +120,15 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
// 1.0 get additional coverage info
if ( !mCapabilities.describeCoverage( mIdentifier ) )
{
QgsMessageLog::logMessage( tr( "Cannot describe coverage" ), tr( "WCS" ) );
appendError( ERR( tr( "Cannot describe coverage" ) ) );
return;
}

mCoverageSummary = mCapabilities.coverage( mIdentifier );
if ( !mCoverageSummary.valid )
{
// Should not happen if describeCoverage() did not fail
QgsMessageLog::logMessage( tr( "Coverage not found" ), tr( "WCS" ) );
appendError( ERR( tr( "Coverage not found" ) ) );
return;
}

Expand Down Expand Up @@ -182,7 +185,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )

if ( !calculateExtent() )
{
QgsMessageLog::logMessage( tr( "Cannot calculate extent" ), tr( "WCS" ) );
appendError( ERR( tr( "Cannot calculate extent" ) ) );
return;
}

Expand Down Expand Up @@ -239,7 +242,8 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )

if ( !mCachedGdalDataset )
{
QgsMessageLog::logMessage( tr( "Cannot get test dataset." ), tr( "WCS" ) );
setError( mCachedError );
appendError( ERR( tr( "Cannot get test dataset." ) ) );
return;
}

Expand Down Expand Up @@ -871,9 +875,9 @@ void QgsWcsProvider::cacheReplyFinished()
contentType.startsWith( "application/vnd.ogc.se_xml", Qt::CaseInsensitive ) )
&& parseServiceExceptionReportDom( text ) )
{
QgsMessageLog::logMessage( tr( "Map request error (Title:%1; Error:%2; URL: %3)" )
.arg( mErrorCaption ).arg( mError )
.arg( mCacheReply->url().toString() ), tr( "WCS" ) );
mCachedError.append( SRVERR( tr( "Map request error:<br>Title: %1<br>Error: %2<br>URL: <a href='%3'>%3</a>)" )
.arg( mErrorCaption ).arg( mError )
.arg( mCacheReply->url().toString() ) ) );
}
else
{
Expand Down Expand Up @@ -1186,6 +1190,7 @@ void QgsWcsProvider::clearCache()
}
QgsDebugMsg( "Clear mCachedData" );
mCachedData.clear();
mCachedError.clear();
QgsDebugMsg( "Cleared" );
}

Expand Down Expand Up @@ -1456,6 +1461,7 @@ bool QgsWcsProvider::calculateExtent()
else
{
QgsDebugMsg( "Cannot get cache to verify extent" );
setError( mCachedError );
return false;
}

Expand Down
20 changes: 3 additions & 17 deletions src/providers/wcs/qgswcsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#ifndef QGSWCSPROVIDER_H
#define QGSWCSPROVIDER_H

#include "qgserror.h"
#include "qgswcscapabilities.h"
#include "qgsrasterdataprovider.h"
#include "qgsgdalproviderbase.h"
Expand Down Expand Up @@ -162,13 +163,6 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
void reloadData();
QList<QgsColorRampShader::ColorRampItem> colorTable( int bandNo )const;

// WMS specific, maybe to be removed from QgsRasterDataProvider
void addLayers( QStringList const &layers, QStringList const &styles = QStringList() ) { Q_UNUSED( layers ); Q_UNUSED( styles ); }
QStringList supportedImageEncodings() { return QStringList(); }
QString imageEncoding() const { return QString(); }
void setImageEncoding( QString const &mimeType ) { Q_UNUSED( mimeType ); }
void setImageCrs( QString const &crs ) { Q_UNUSED( crs ); }

static QMap<QString, QString> supportedMimes();

signals:
Expand Down Expand Up @@ -348,16 +342,8 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
/** Pointer to cached GDAL dataset */
GDALDatasetH mCachedGdalDataset;

/** \brief Values for mapping pixel to world coordinates. Contents of this array are the same as the GDAL adfGeoTransform */
//double mGeoTransform[6];

/**
* The previously retrieved image from the WCS server.
* This can be reused if draw() is called consecutively
* with the same parameters.
*/
//QImage *mCachedImage;

/** Current cache error last getCache() error. */
QgsError mCachedError;

/** The previous parameters to draw(). */
QgsRectangle mCachedViewExtent;
Expand Down
65 changes: 49 additions & 16 deletions src/providers/wms/qgswmsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
#include <QDir>
#endif

#define ERR(message) QGS_ERROR_MESSAGE(message,"WMS provider")
#define SRVERR(message) QGS_ERROR_MESSAGE(message,"WMS server")

static QString WMS_KEY = "wms";
static QString WMS_DESCRIPTION = "OGC Web Map Service version 1.3 data provider";

Expand Down Expand Up @@ -93,13 +96,22 @@ QgsWmsProvider::QgsWmsProvider( QString const &uri )
{
QgsDebugMsg( "constructing with uri '" + mHttpUri + "'." );

// assume this is a valid layer until we determine otherwise
mValid = true;
mValid = false;

// URL may contain username/password information for a WMS
// requiring authentication. In this case the URL is prefixed
// with username=user,password=pass,url=http://xxx.xxx.xx/yyy...
parseUri( uri );
if ( !parseUri( uri ) )
{
appendError( ERR( tr( "Cannot parse URI" ) ) );
return;
}

if ( !calculateExtent() || mLayerExtent.isEmpty() )
{
appendError( ERR( tr( "Cannot calculate extent" ) ) );
return;
}

// URL can be in 3 forms:
// 1) http://xxx.xxx.xx/yyy/yyy
Expand All @@ -109,12 +121,12 @@ QgsWmsProvider::QgsWmsProvider( QString const &uri )

mSupportedGetFeatureFormats = QStringList() << "text/html" << "text/plain" << "text/xml";

mValid = true;
QgsDebugMsg( "exiting constructor." );
}

void QgsWmsProvider::parseUri( QString uriString )
bool QgsWmsProvider::parseUri( QString uriString )
{

QgsDebugMsg( "uriString = " + uriString );
QgsDataSourceURI uri;
uri.setEncodedUri( uriString );
Expand Down Expand Up @@ -181,11 +193,16 @@ void QgsWmsProvider::parseUri( QString uriString )
}

// setImageCrs is using mTiled !!!
setImageCrs( uri.param( "crs" ) );
if ( !setImageCrs( uri.param( "crs" ) ) )
{
appendError( ERR( tr( "Cannot set CRS" ) ) );
return false;
}
mCrs.createFromOgcWmsCrs( uri.param( "crs" ) );

mFeatureCount = uri.param( "featureCount" ).toInt(); // default to 0

return true;
}

QString QgsWmsProvider::prepareUri( QString uri ) const
Expand Down Expand Up @@ -398,7 +415,7 @@ void QgsWmsProvider::setImageEncoding( QString const & mimeType )
}


void QgsWmsProvider::setImageCrs( QString const & crs )
bool QgsWmsProvider::setImageCrs( QString const & crs )
{
QgsDebugMsg( "Setting image CRS to " + crs + "." );

Expand All @@ -420,17 +437,20 @@ void QgsWmsProvider::setImageCrs( QString const & crs )
{
if ( mActiveSubLayers.size() != 1 )
{
QgsDebugMsg( "Number of tile layers must be one" );
mValid = false;
return;
appendError( ERR( tr( "Number of tile layers must be one" ) ) );
return false;
}

mValid = retrieveServerCapabilities();
QgsDebugMsg( QString( "mValid = %1 mTileLayersSupported.size() = %2" ).arg( mValid ).arg( mTileLayersSupported.size() ) );
if ( !mValid || mTileLayersSupported.size() == 0 )
if ( !retrieveServerCapabilities() )
{
QgsDebugMsg( "Tile layer not found" );
return;
// Error set in retrieveServerCapabilities()
return false;
}
QgsDebugMsg( QString( "mTileLayersSupported.size() = %1" ).arg( mTileLayersSupported.size() ) );
if ( mTileLayersSupported.size() == 0 )
{
appendError( ERR( tr( "Tile layer not found" ) ) );
return false;
}

for ( int i = 0; i < mTileLayersSupported.size(); i++ )
Expand Down Expand Up @@ -483,8 +503,13 @@ void QgsWmsProvider::setImageCrs( QString const & crs )

setProperty( "resolutions", resolutions );

mValid = mTileLayer != 0 && mTileMatrixSet != 0;
if ( mTileLayer == 0 && mTileMatrixSet == 0 )
{
appendError( ERR( tr( "Tile layer or tile matrix set not found" ) ) );
return false;
}
}
return true;
}

void QgsWmsProvider::setQueryItem( QUrl &url, QString item, QString value )
Expand Down Expand Up @@ -3120,6 +3145,13 @@ bool QgsWmsProvider::calculateExtent()
{
QgsDebugMsg( "Sublayer Iterator: " + *it );
// This is the extent for the layer name in *it
if ( !mExtentForLayer.contains( *it ) )
{
mLayerExtent = QgsRectangle();
appendError( ERR( tr( "Extent for layer %1 not found in capabilities" ).arg( *it ) ) );
return false;
}

QgsRectangle extent = mExtentForLayer.find( *it ).value();

// Convert to the user's CRS as required
Expand Down Expand Up @@ -3159,6 +3191,7 @@ bool QgsWmsProvider::calculateExtent()
QgsDebugMsg( "exiting with '" + mLayerExtent.toString() + "'." );
return true;
}
return false; // should not be reached
}


Expand Down
4 changes: 2 additions & 2 deletions src/providers/wms/qgswmsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ class QgsWmsProvider : public QgsRasterDataProvider
*
* \note an empty crs value will result in the previous CRS being retained.
*/
void setImageCrs( QString const & crs );
bool setImageCrs( QString const & crs );

/**
* Set the name of the connection for use in authentication where required
Expand Down Expand Up @@ -846,7 +846,7 @@ class QgsWmsProvider : public QgsRasterDataProvider
* \note added in 1.1
*/

void parseUri( QString uri );
bool parseUri( QString uri );

/**
* \brief Prepare the URI so that we can later simply append param=value
Expand Down
162 changes: 162 additions & 0 deletions src/ui/qgserrordialogbase.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsErrorDialogBase</class>
<widget class="QDialog" name="QgsErrorDialogBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>580</width>
<height>208</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="mIconLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>../../images/themes/default/mIconWarn.png</pixmap>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="mSummaryTextBrowser">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Summary&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="mDetailTextBrowser">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Detailed report.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="mDetailCheckBox">
<property name="text">
<string>Always show details</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="mDetailPushButton">
<property name="text">
<string>Details &gt;&gt;</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QgsErrorDialogBase</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QgsErrorDialogBase</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>