mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
QgsError for better error propagation to user, started using for rasters
This commit is contained in:
parent
b78456f70d
commit
e210a57101
@ -559,9 +559,26 @@ IF (GIT_MARKER)
|
||||
COMMAND ${GITCOMMAND} log -n1 --pretty=%h OUTPUT_VARIABLE REVISION
|
||||
)
|
||||
STRING(STRIP "${REVISION}" REVISION)
|
||||
# Get GIT remote and branch
|
||||
EXECUTE_PROCESS(
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMAND ${GITCOMMAND} name-rev --name-only HEAD OUTPUT_VARIABLE GIT_LOCAL_BRANCH
|
||||
)
|
||||
STRING(STRIP "${GIT_LOCAL_BRANCH}" GIT_LOCAL_BRANCH)
|
||||
EXECUTE_PROCESS(
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMAND ${GITCOMMAND} config branch.${GIT_LOCAL_BRANCH}.remote OUTPUT_VARIABLE GIT_REMOTE
|
||||
)
|
||||
STRING(STRIP "${GIT_REMOTE}" GIT_REMOTE)
|
||||
EXECUTE_PROCESS(
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMAND ${GITCOMMAND} config remote.${GIT_REMOTE}.url OUTPUT_VARIABLE GIT_REMOTE_URL
|
||||
)
|
||||
STRING(STRIP "${GIT_REMOTE_URL}" GIT_REMOTE_URL)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/qgsversion.h
|
||||
COMMAND echo \\\#define QGSVERSION \\\"${REVISION}\\\" >${CMAKE_CURRENT_BINARY_DIR}/qgsversion.h
|
||||
COMMAND echo \\\#define QGS_GIT_REMOTE_URL \\\"${GIT_REMOTE_URL}\\\" >>${CMAKE_CURRENT_BINARY_DIR}/qgsversion.h
|
||||
MAIN_DEPENDENCY ${GIT_MARKER}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
|
@ -99,31 +99,6 @@ class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface
|
||||
/* It makes no sense to set input on provider */
|
||||
bool setInput( QgsRasterInterface* input );
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -147,10 +147,6 @@ class QgsRasterLayer : 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;
|
||||
|
||||
|
@ -120,6 +120,8 @@
|
||||
#include "qgsdecorationscalebar.h"
|
||||
#include "qgsdecorationgrid.h"
|
||||
#include "qgsencodingfiledialog.h"
|
||||
#include "qgserror.h"
|
||||
#include "qgserrordialog.h"
|
||||
#include "qgsexception.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsformannotationitem.h"
|
||||
@ -7294,6 +7296,14 @@ QgsRasterLayer* QgisApp::addRasterLayer( QString const & rasterFile, QString con
|
||||
QgsRasterLayer *layer =
|
||||
new QgsRasterLayer( rasterFile, baseName ); // fi.completeBaseName());
|
||||
|
||||
if ( !layer->isValid() )
|
||||
{
|
||||
//QMessageBox::critical( this, tr( "Invalid Layer" ), layer->error().message() );
|
||||
QgsErrorDialog::show( layer->error(), tr( "Invalid Layer" ) );
|
||||
delete layer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
|
||||
if ( shouldAskUserForGDALSublayers( layer ) )
|
||||
@ -7377,7 +7387,7 @@ QgsRasterLayer* QgisApp::addRasterLayer(
|
||||
|
||||
QgsDebugMsg( "Constructed new layer." );
|
||||
|
||||
if ( layer && layer->isValid() )
|
||||
if ( layer->isValid() )
|
||||
{
|
||||
addRasterLayer( layer );
|
||||
|
||||
@ -7385,8 +7395,7 @@ QgsRasterLayer* QgisApp::addRasterLayer(
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical( this, tr( "Layer is not valid" ),
|
||||
tr( "The layer is not a valid layer and can not be added to the map" ) );
|
||||
QgsErrorDialog::show( layer->error(), tr( "Invalid Layer" ) );
|
||||
}
|
||||
|
||||
// update UI
|
||||
@ -7454,25 +7463,37 @@ bool QgisApp::addRasterLayers( QStringList const &theFileNameQStringList, bool g
|
||||
// create the layer
|
||||
QgsRasterLayer *layer = new QgsRasterLayer( *myIterator, myBaseNameQString );
|
||||
|
||||
if ( shouldAskUserForGDALSublayers( layer ) )
|
||||
if ( !layer->isValid() )
|
||||
{
|
||||
askUserForGDALSublayers( layer );
|
||||
|
||||
// The first layer loaded is not useful in that case. The user can select it in
|
||||
// the list if he wants to load it.
|
||||
delete layer;
|
||||
returnValue = false;
|
||||
if ( guiWarning )
|
||||
{
|
||||
QgsErrorDialog::show( layer->error(), tr( "Invalid Layer" ) );
|
||||
delete layer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addRasterLayer( layer );
|
||||
|
||||
//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.toLower().endsWith( ".adf" ) )
|
||||
if ( shouldAskUserForGDALSublayers( layer ) )
|
||||
{
|
||||
break;
|
||||
askUserForGDALSublayers( layer );
|
||||
|
||||
// The first layer loaded is not useful in that case. The user can select it in
|
||||
// the list if he wants to load it.
|
||||
delete layer;
|
||||
}
|
||||
else
|
||||
{
|
||||
addRasterLayer( layer );
|
||||
|
||||
//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.toLower().endsWith( ".adf" ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // valid raster filename
|
||||
|
@ -63,6 +63,7 @@ SET(QGIS_CORE_SRCS
|
||||
qgsdbfilterproxymodel.cpp
|
||||
qgsdiagramrendererv2.cpp
|
||||
qgsdistancearea.cpp
|
||||
qgserror.cpp
|
||||
qgsexpression.cpp
|
||||
qgsfeature.cpp
|
||||
qgsfield.cpp
|
||||
@ -350,6 +351,7 @@ SET(QGIS_CORE_HDRS
|
||||
qgsdataitem.h
|
||||
qgsdistancearea.h
|
||||
qgscsexception.h
|
||||
qgserror.h
|
||||
qgsexception.h
|
||||
qgsexpression.h
|
||||
qgsfeature.h
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <QStringList>
|
||||
|
||||
//#include "qgsdataitem.h"
|
||||
#include "qgserror.h"
|
||||
|
||||
class QgsRectangle;
|
||||
class QgsCoordinateReferenceSystem;
|
||||
@ -290,6 +291,12 @@ class CORE_EXPORT QgsDataProvider : public QObject
|
||||
/** Current time stamp of data source */
|
||||
virtual QDateTime dataTimestamp() const { return QDateTime(); }
|
||||
|
||||
/** Get current status error. This error describes some principal problem
|
||||
* for which provider cannot work and thus is not valid. It is not last error
|
||||
* after accessing data by block(), identify() etc.
|
||||
*/
|
||||
virtual QgsError error() const { return mError; }
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
@ -318,6 +325,16 @@ class CORE_EXPORT QgsDataProvider : public QObject
|
||||
* Timestamp of data in the moment when the data were loaded by provider.
|
||||
*/
|
||||
QDateTime mTimestamp;
|
||||
|
||||
/** \brief Error */
|
||||
QgsError mError;
|
||||
|
||||
/** Add error message */
|
||||
void appendError( const QgsErrorMessage & theMessage ) { mError.append( theMessage );}
|
||||
|
||||
/** Set error message */
|
||||
void setError( const QgsError & theError ) { mError = theError;}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
111
src/core/qgserror.cpp
Normal file
111
src/core/qgserror.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/***************************************************************************
|
||||
qgserror.cpp - 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgis.h"
|
||||
#include "qgsversion.h"
|
||||
#include "qgsconfig.h"
|
||||
#include "qgserror.h"
|
||||
#include "qgslogger.h"
|
||||
|
||||
#include <QRegExp>
|
||||
|
||||
QgsErrorMessage::QgsErrorMessage ( const QString & theMessage, const QString & theTag, const QString & theFile, const QString & theFunction, int theLine )
|
||||
: mMessage(theMessage)
|
||||
, mTag(theTag)
|
||||
, mFile(theFile)
|
||||
, mFunction(theFunction)
|
||||
, mLine(theLine)
|
||||
, mFormat(Text)
|
||||
{
|
||||
}
|
||||
|
||||
QgsError::QgsError ( const QString & theMessage, const QString & theTag )
|
||||
{
|
||||
append ( theMessage, theTag );
|
||||
}
|
||||
|
||||
void QgsError::append ( const QString & theMessage, const QString & theTag )
|
||||
{
|
||||
mMessageList.append ( QgsErrorMessage ( theMessage, theTag ) );
|
||||
}
|
||||
|
||||
void QgsError::append ( const QgsErrorMessage & theMessage )
|
||||
{
|
||||
mMessageList.append ( theMessage );
|
||||
}
|
||||
|
||||
QString QgsError::message ( QgsErrorMessage::Format theFormat ) const
|
||||
{
|
||||
QString str;
|
||||
int sPrefixLength = strlen( CMAKE_SOURCE_DIR ) + 1;
|
||||
|
||||
QString srcUrl;
|
||||
#if defined(QGISDEBUG) && defined(QGS_GIT_REMOTE_URL)
|
||||
// TODO: verify if we are not ahead to origin (remote hash does not exist)
|
||||
// and there are no local not commited changes
|
||||
QString hash = QString(QGis::QGIS_DEV_VERSION);
|
||||
QString remote = QString(QGS_GIT_REMOTE_URL);
|
||||
QgsDebugMsg ("remote = " + remote );
|
||||
if ( !hash.isEmpty () && !remote.isEmpty() && remote.contains ( "github.com" ) )
|
||||
{
|
||||
QString path = remote.remove( QRegExp(".*github.com[:/]" )).remove(".git");
|
||||
srcUrl = "https://github.com/" + path + "/blob/" + hash;
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach ( QgsErrorMessage m, mMessageList )
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
QString file;
|
||||
#ifndef _MSC_VER
|
||||
file = m.file().mid(sPrefixLength);
|
||||
#else
|
||||
file = m.file();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ( theFormat == QgsErrorMessage::Text )
|
||||
{
|
||||
str += m.tag() + " " + m.message();
|
||||
#ifdef QGISDEBUG
|
||||
str += QString( "\nat %1 : %2 : %3" ).arg( file ).arg( m.line() ).arg( m.function() );
|
||||
#endif
|
||||
}
|
||||
else // QgsErrorMessage::Html
|
||||
{
|
||||
str += "<p><b>" + m.tag() + ":</b> " + m.message();
|
||||
#ifdef QGISDEBUG
|
||||
QString location = QString( "%1 : %2 : %3" ).arg( file ).arg( m.line() ).arg( m.function() );
|
||||
if ( !srcUrl.isEmpty() )
|
||||
{
|
||||
QString url = QString("%1/%2#L%3").arg(srcUrl).arg(file).arg( m.line() );
|
||||
str += QString( "<br>(<a href='%1'>%2</a>)" ).arg(url).arg( location );
|
||||
}
|
||||
else
|
||||
{
|
||||
str += QString( "<br>(%1)" ).arg( location );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
QString QgsError::summary ( ) const
|
||||
{
|
||||
// The first message in chain is usually the real error given by backend/server
|
||||
return mMessageList.first().message();
|
||||
}
|
124
src/core/qgserror.h
Normal file
124
src/core/qgserror.h
Normal file
@ -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
|
@ -26,6 +26,7 @@
|
||||
#include <QDomNode>
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgserror.h"
|
||||
#include "qgsrectangle.h"
|
||||
|
||||
class QgsRenderContext;
|
||||
@ -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
|
||||
*/
|
||||
@ -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;
|
||||
|
||||
@ -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 */
|
||||
|
@ -449,6 +449,7 @@ void * QgsProviderRegistry::function( QString const & providerKey,
|
||||
delete myLib;
|
||||
return ptr;
|
||||
}
|
||||
QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
|
||||
delete myLib;
|
||||
return 0;
|
||||
}
|
||||
@ -467,6 +468,7 @@ QLibrary *QgsProviderRegistry::providerLibrary( QString const & providerKey ) co
|
||||
{
|
||||
return myLib;
|
||||
}
|
||||
QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
|
||||
delete myLib;
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsrasterchecker.h"
|
||||
#include "qgsrasterdataprovider.h"
|
||||
#include "qgsrasterlayer.h"
|
||||
@ -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 );
|
||||
|
@ -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"
|
||||
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
@ -121,6 +123,7 @@ QgsRasterLayer::QgsRasterLayer(
|
||||
// TODO, call constructor with provider key
|
||||
init();
|
||||
setDataProvider( "gdal" );
|
||||
if ( !mValid ) return;
|
||||
|
||||
bool defaultLoadedFlag = false;
|
||||
if ( mValid && loadDefaultStyleFlag )
|
||||
@ -157,6 +160,7 @@ QgsRasterLayer::QgsRasterLayer( const QString & uri,
|
||||
QgsDebugMsg( "Entered" );
|
||||
init();
|
||||
setDataProvider( providerKey );
|
||||
if ( !mValid ) return;
|
||||
|
||||
// load default style
|
||||
bool defaultLoadedFlag = false;
|
||||
@ -189,6 +193,7 @@ QgsRasterLayer::QgsRasterLayer( const QString & uri,
|
||||
QgsRasterLayer::~QgsRasterLayer()
|
||||
{
|
||||
mValid = false;
|
||||
//delete mDataProvider; // deleted by pipe
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
@ -207,21 +212,14 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,14 +227,7 @@ void QgsRasterLayer::buildSupportedRasterFileFilter( QString & theFileFiltersStr
|
||||
*/
|
||||
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" );
|
||||
@ -244,7 +235,6 @@ bool QgsRasterLayer::isValidRasterFileName( QString const & theFileNameQString,
|
||||
}
|
||||
|
||||
bool myIsValid = pValid( theFileNameQString, retErrMsg );
|
||||
delete myLib;
|
||||
return myIsValid;
|
||||
}
|
||||
|
||||
@ -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 )
|
||||
{
|
||||
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" ) );
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** Copied from QgsVectorLayer::setDataProvider
|
||||
* TODO: Make it work in the raster environment
|
||||
*/
|
||||
void QgsRasterLayer::setDataProvider( QString const & provider )
|
||||
{
|
||||
QgsDebugMsg( "Entered" );
|
||||
mValid = false; // assume the layer is invalid until we determine otherwise
|
||||
|
||||
mPipe.remove( mDataProvider ); // deletes if exists
|
||||
mDataProvider = 0;
|
||||
|
||||
// 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?
|
||||
{
|
||||
@ -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 );
|
||||
@ -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 );
|
||||
@ -2644,6 +2562,7 @@ bool QgsRasterLayer::readXml( const QDomNode& layer_node )
|
||||
closeDataProvider();
|
||||
init();
|
||||
setDataProvider( mProviderKey );
|
||||
if ( !mValid ) return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -56,6 +56,7 @@ qgsdetaileditemwidget.cpp
|
||||
qgsdetaileditemdata.cpp
|
||||
qgsdialog.cpp
|
||||
qgsencodingfiledialog.cpp
|
||||
qgserrordialog.cpp
|
||||
qgsfiledropedit.cpp
|
||||
qgsfieldvalidator.cpp
|
||||
qgsformannotationitem.cpp
|
||||
@ -155,6 +156,7 @@ qgsdialog.h
|
||||
qgslegendinterface.h
|
||||
qgisinterface.h
|
||||
qgsencodingfiledialog.h
|
||||
qgserrordialog.h
|
||||
qgsfieldvalidator.h
|
||||
qgsformannotationitem.h
|
||||
qgshtmlannotationitem.h
|
||||
|
79
src/gui/qgserrordialog.cpp
Normal file
79
src/gui/qgserrordialog.cpp
Normal file
@ -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
src/gui/qgserrordialog.h
Normal file
46
src/gui/qgserrordialog.h
Normal file
@ -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
|
@ -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";
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
@ -133,6 +138,7 @@ QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
|
||||
{
|
||||
mYBlockSize = mRows;
|
||||
}
|
||||
mValid = true;
|
||||
QgsDebugMsg( "mYBlockSize = " + QString::number( mYBlockSize ) );
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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";
|
||||
|
||||
@ -117,7 +120,7 @@ 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;
|
||||
}
|
||||
|
||||
@ -125,7 +128,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
{
|
||||
@ -1186,6 +1190,7 @@ void QgsWcsProvider::clearCache()
|
||||
}
|
||||
QgsDebugMsg( "Clear mCachedData" );
|
||||
mCachedData.clear();
|
||||
mCachedError.clear();
|
||||
QgsDebugMsg( "Cleared" );
|
||||
}
|
||||
|
||||
@ -1456,6 +1461,7 @@ bool QgsWcsProvider::calculateExtent()
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( "Cannot get cache to verify extent" );
|
||||
setError( mCachedError );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#ifndef QGSWCSPROVIDER_H
|
||||
#define QGSWCSPROVIDER_H
|
||||
|
||||
#include "qgserror.h"
|
||||
#include "qgswcscapabilities.h"
|
||||
#include "qgsrasterdataprovider.h"
|
||||
#include "qgsgdalproviderbase.h"
|
||||
@ -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:
|
||||
@ -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;
|
||||
|
@ -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";
|
||||
|
||||
@ -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
|
||||
@ -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 );
|
||||
@ -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
|
||||
@ -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 + "." );
|
||||
|
||||
@ -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++ )
|
||||
@ -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 )
|
||||
@ -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
|
||||
@ -3159,6 +3191,7 @@ bool QgsWmsProvider::calculateExtent()
|
||||
QgsDebugMsg( "exiting with '" + mLayerExtent.toString() + "'." );
|
||||
return true;
|
||||
}
|
||||
return false; // should not be reached
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
@ -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
|
||||
|
162
src/ui/qgserrordialogbase.ui
Normal file
162
src/ui/qgserrordialogbase.ui
Normal file
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Summary</p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Detailed report.</p></body></html></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 >></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>
|
Loading…
x
Reference in New Issue
Block a user