QgsReadWriteContext: add a category stack to know where the error message comes from

also change the QPair in favor of a struct for a better API
This commit is contained in:
Denis Rouzaud 2018-02-26 14:08:03 -04:00
parent 22008a5114
commit b95f5c1a15
10 changed files with 161 additions and 14 deletions

View File

@ -912,7 +912,7 @@ Emitted when a layer from a projects was read.
void loadingLayer( const QString &layerName );
void loadingLayerMessages( const QString &layerName, const QList<QPair<Qgis::MessageLevel, QString>> &messages );
void loadingLayerMessages( const QString &layerName, const QList<QgsReadWriteContext::ReadWriteMessage> &messages );
%Docstring
Emitted when loading layers has produced some messages
@param layerName the layer name

View File

@ -22,11 +22,37 @@ The class is used as a container of context for various read/write operations on
%End
public:
struct ReadWriteMessage
{
ReadWriteMessage( const QString &message, Qgis::MessageLevel level = Qgis::Warning, QStringList categories = QStringList() );
%Docstring
Construct a container for QgsReadWriteContext error or warning messages
%End
QString message() const;
%Docstring
Return the message string
%End
Qgis::MessageLevel level() const;
%Docstring
Return the message level
%End
QStringList categories() const;
%Docstring
Return the stack of categories of the message
%End
};
QgsReadWriteContext();
%Docstring
Constructor for QgsReadWriteContext.
%End
~QgsReadWriteContext();
const QgsPathResolver &pathResolver() const;
%Docstring
Returns path resolver for conversion between relative and absolute paths
@ -37,14 +63,32 @@ Returns path resolver for conversion between relative and absolute paths
Sets up path resolver for conversion between relative and absolute paths
%End
void pushMessage( Qgis::MessageLevel level, const QString &message );
void pushMessage( const QString &message, Qgis::MessageLevel level );
%Docstring
append a message to the context
.. versionadded:: 3.2
%End
QList<QPair<Qgis::MessageLevel, QString>> takeMessages();
void enterCategory( const QString &category, const QString &details = QString() );
%Docstring
Push a category to the stack
.. versionadded:: 3.2
%End
void leaveCategory();
%Docstring
Pop the last category
.. versionadded:: 3.2
%End
QList<QgsReadWriteContext::ReadWriteMessage> takeMessages();
%Docstring
return the stored messages and remove them
.. versionadded:: 3.2
%End
};

View File

@ -11240,11 +11240,11 @@ void QgisApp::showStatusMessage( const QString &message )
mStatusBar->showMessage( message );
}
void QgisApp::loadingLayerMessages( const QString &layerName, const QList<QPair<Qgis::MessageLevel, QString> > &messages )
void QgisApp::loadingLayerMessages( const QString &layerName, const QList<QgsReadWriteContext::ReadWriteMessage> &messages )
{
for ( const auto message : messages )
{
messageBar()->pushMessage( layerName, message.second, message.first );
messageBar()->pushMessage( layerName, message.message(), message.level() );
}
}

View File

@ -926,7 +926,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void showProgress( int progress, int totalSteps );
void showStatusMessage( const QString &message );
void loadingLayerMessages( const QString &layerName, const QList<QPair<Qgis::MessageLevel, QString>> &messages );
void loadingLayerMessages( const QString &layerName, const QList<QgsReadWriteContext::ReadWriteMessage> &messages );
//! set the active layer
bool setActiveLayer( QgsMapLayer * );

View File

@ -260,6 +260,7 @@ void QgsEditFormConfig::setSuppress( QgsEditFormConfig::FeatureFormSuppress s )
void QgsEditFormConfig::readXml( const QDomNode &node, QgsReadWriteContext &context )
{
context.enterCategory( QString( "Edit form config" ) );
d.detach();
QDomNode editFormNode = node.namedItem( QStringLiteral( "editform" ) );
@ -387,6 +388,8 @@ void QgsEditFormConfig::readXml( const QDomNode &node, QgsReadWriteContext &cont
onRelationsLoaded();
}
}
context.leaveCategory();
}
void QgsEditFormConfig::writeXml( QDomNode &node, const QgsReadWriteContext &context ) const

View File

@ -430,6 +430,8 @@ bool QgsMapLayer::readLayerXml( const QDomElement &layerElement, QgsReadWriteCo
// the subclass can also read custom properties
readCustomProperties( layerElement );
context.enterCategory( tr( "Layer" ), mne.text() );
// now let the children grab what they need from the Dom node.
layerError = !readXml( layerElement, context );
@ -555,6 +557,8 @@ bool QgsMapLayer::readLayerXml( const QDomElement &layerElement, QgsReadWriteCo
QDomElement metadataElem = layerElement.firstChildElement( QStringLiteral( "resourceMetadata" ) );
mMetadata.readMetadataXml( metadataElem );
context.leaveCategory();
return true;
} // bool QgsMapLayer::readLayerXML

View File

@ -42,6 +42,7 @@
#include "qgsmaplayer.h"
#include "qgsmaplayerstore.h"
#include "qgsarchive.h"
#include "qgsreadwritecontext.h"
class QFileInfo;
class QDomDocument;
@ -894,7 +895,7 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
* @param layerName the layer name
* @param messages a list of pairs of Qgis::MessageLevel and messages
*/
void loadingLayerMessages( const QString &layerName, const QList<QPair<Qgis::MessageLevel, QString>> &messages );
void loadingLayerMessages( const QString &layerName, const QList<QgsReadWriteContext::ReadWriteMessage> &messages );
//! Emitted when the list of layer which are excluded from map identification changes
void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );

View File

@ -13,3 +13,45 @@
* *
***************************************************************************/
#include "qgsreadwritecontext.h"
QgsReadWriteContext::~QgsReadWriteContext()
{
// be sure that categories have been emptied
Q_ASSERT( mCategories.isEmpty() );
}
const QgsPathResolver &QgsReadWriteContext::pathResolver() const
{
return mPathResolver;
}
void QgsReadWriteContext::setPathResolver( const QgsPathResolver &resolver )
{
mPathResolver = resolver;
}
void QgsReadWriteContext::pushMessage( const QString &message, Qgis::MessageLevel level )
{
mMessages.append( ReadWriteMessage( message, level, mCategories ) );
}
void QgsReadWriteContext::enterCategory( const QString &category, const QString &details )
{
QString message = category;
if ( !details.isEmpty() )
message.append( QString( " :: %1" ).arg( details ) );
mCategories.push_front( message );
}
void QgsReadWriteContext::leaveCategory()
{
if ( !mCategories.isEmpty() )
mCategories.pop_front();
}
QList<QgsReadWriteContext::ReadWriteMessage > QgsReadWriteContext::takeMessages()
{
QList<QgsReadWriteContext::ReadWriteMessage > messages = mMessages;
mMessages.clear();
return messages;
}

View File

@ -31,26 +31,75 @@ class CORE_EXPORT QgsReadWriteContext
{
public:
/**
* Struct for QgsReadWriteContext error or warning messages
* \since QGIS 3.2
*/
struct ReadWriteMessage
{
//! Construct a container for QgsReadWriteContext error or warning messages
ReadWriteMessage( const QString &message, Qgis::MessageLevel level = Qgis::Warning, QStringList categories = QStringList() )
: mMessage( message )
, mLevel( level )
, mCategories( categories )
{}
//! Return the message string
QString message() const {return mMessage;}
//! Return the message level
Qgis::MessageLevel level() const {return mLevel;}
//! Return the stack of categories of the message
QStringList categories() const {return mCategories;}
private:
QString mMessage = QString();
Qgis::MessageLevel mLevel = Qgis::Warning;
QStringList mCategories = QStringList();
};
/**
* Constructor for QgsReadWriteContext.
*/
QgsReadWriteContext() = default;
~QgsReadWriteContext();
//! Returns path resolver for conversion between relative and absolute paths
const QgsPathResolver &pathResolver() const { return mPathResolver; }
const QgsPathResolver &pathResolver() const;
//! Sets up path resolver for conversion between relative and absolute paths
void setPathResolver( const QgsPathResolver &resolver ) { mPathResolver = resolver; }
void setPathResolver( const QgsPathResolver &resolver );
//! append a message to the context
void pushMessage( Qgis::MessageLevel level, const QString &message ) {mMessages.append( qMakePair( level, message ) );}
/**
* append a message to the context
* \since QGIS 3.2
*/
void pushMessage( const QString &message, Qgis::MessageLevel level );
//! return the stored messages and remove them
QList<QPair<Qgis::MessageLevel, QString>> takeMessages() {return mMessages; mMessages.clear();}
/**
* Push a category to the stack
* \since QGIS 3.2
*/
void enterCategory( const QString &category, const QString &details = QString() );
/**
* Pop the last category
* \since QGIS 3.2
*/
void leaveCategory();
/**
* return the stored messages and remove them
* \since QGIS 3.2
*/
QList<QgsReadWriteContext::ReadWriteMessage> takeMessages();
private:
QgsPathResolver mPathResolver;
QList<QPair<Qgis::MessageLevel, QString>> mMessages;
QList<ReadWriteMessage> mMessages;
QStringList mCategories = QStringList();
};
#endif // QGSREADWRITECONTEXT_H

View File

@ -1688,6 +1688,8 @@ void QgsVectorLayer::resolveReferences( QgsProject *project )
bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage, QgsReadWriteContext &context )
{
context.enterCategory( tr( "Symbology" ) );
if ( !mExpressionFieldBuffer )
mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
mExpressionFieldBuffer->readXml( layerNode );
@ -1873,6 +1875,8 @@ bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMes
updateFields();
context.leaveCategory();
return true;
}