Skip to content

Commit

Permalink
Add API for temporarily suppressing user notifications for
Browse files Browse the repository at this point in the history
message log critical/warning messages

These messages are still logged, but the log indicator is not
modified to flag their appearance.

This allows certain error messages to be logged (e.g. on startup)
which cannot be fixed by users/developers (e.g. those caused
by upstream Qt issues, 3rd party Python libraries, etc) but
without flagging them.

Currently, we get so many of these warnings on startup that the
log indicator loses all impact, and newly introduced, VALID
errors go unnoticed/ignored.
  • Loading branch information
nyalldawson committed Jun 18, 2018
1 parent 00f0583 commit 949853a
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 9 deletions.
59 changes: 57 additions & 2 deletions python/core/auto_generated/qgsmessagelog.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,71 @@ QgsMessageLog is not usually directly created, but rather accessed through
Constructor for QgsMessageLog.
%End

static void logMessage( const QString &message, const QString &tag = QString(), Qgis::MessageLevel level = Qgis::Warning );
static void logMessage( const QString &message, const QString &tag = QString(), Qgis::MessageLevel level = Qgis::Warning, bool notifyUser = true );
%Docstring
add a message to the instance (and create it if necessary)
Adds a ``message`` to the log instance (and creates it if necessary).

If ``notifyUser`` is true, then the message should be brought to the user's attention by various UI hints.
If it is false, the message should appear in logs silently. Note that log viewer implementations may
only respect notification hints for certain message levels.
%End

signals:

void messageReceived( const QString &message, const QString &tag, Qgis::MessageLevel level );
%Docstring
Emitted whenever the log receives a ``message``.

This signal is emitted for all messages received by the log, regardless of the ``notifyUser`` flag's
value for the message.
%End


void messageReceived( bool received );
%Docstring
Emitted whenever the log receives a message which has the ``notifyUser`` flag as true.

If QgsMessageLogNotifyBlocker objects have been created then this signal may be
temporarily suppressed.

.. seealso:: :py:class:`QgsMessageLogNotifyBlocker`
%End

};

class QgsMessageLogNotifyBlocker
{
%Docstring
Temporarily blocks the application QgsMessageLog (see QgsApplication.messageLog()) from emitting the messageReceived( bool )
signal for the lifetime of the object.

Using this blocker allows messages to be logged without causing user interface hints flagging message log
errors to be created.

QgsMessageLogNotifyBlocker supports "stacked" blocking, so two QgsMessageLogNotifyBlocker created
will both need to be destroyed before the messageReceived( bool ) signal is emitted again.

.. versionadded:: 3.2
%End

%TypeHeaderCode
#include "qgsmessagelog.h"
%End
public:

QgsMessageLogNotifyBlocker();
%Docstring
Constructor for QgsMessageLogNotifyBlocker.

This will block the log from emitting the messageReceived( bool ) signal for the lifetime of this object.
%End



~QgsMessageLogNotifyBlocker();

private:
QgsMessageLogNotifyBlocker( const QgsMessageLogNotifyBlocker &other );
};

class QgsMessageLogConsole : QObject
Expand Down
21 changes: 17 additions & 4 deletions src/core/qgsmessagelog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@

class QgsMessageLogConsole;

void QgsMessageLog::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
void QgsMessageLog::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level, bool notifyUser )
{
QgsDebugMsg( QStringLiteral( "%1 %2[%3] %4" ).arg( QDateTime::currentDateTime().toString( Qt::ISODate ), tag ).arg( level ).arg( message ) );

QgsApplication::messageLog()->emitMessage( message, tag, level );
QgsApplication::messageLog()->emitMessage( message, tag, level, notifyUser );
}

void QgsMessageLog::emitMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
void QgsMessageLog::emitMessage( const QString &message, const QString &tag, Qgis::MessageLevel level, bool notifyUser )
{
emit messageReceived( message, tag, level );
if ( level != Qgis::Info )
if ( level != Qgis::Info && notifyUser && mAdviseBlockCount == 0 )
{
emit messageReceived( true );
}
Expand All @@ -55,3 +55,16 @@ void QgsMessageLogConsole::logMessage( const QString &message, const QString &ta
<< "]: " << message.toLocal8Bit().data() << std::endl;
}

//
// QgsMessageLogNotifyBlocker
//

QgsMessageLogNotifyBlocker::QgsMessageLogNotifyBlocker()
{
QgsApplication::messageLog()->mAdviseBlockCount++;
}

QgsMessageLogNotifyBlocker::~QgsMessageLogNotifyBlocker()
{
QgsApplication::messageLog()->mAdviseBlockCount--;
}
71 changes: 68 additions & 3 deletions src/core/qgsmessagelog.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,83 @@ class CORE_EXPORT QgsMessageLog : public QObject
*/
QgsMessageLog() = default;

//! add a message to the instance (and create it if necessary)
static void logMessage( const QString &message, const QString &tag = QString(), Qgis::MessageLevel level = Qgis::Warning );
/**
* Adds a \a message to the log instance (and creates it if necessary).
*
* If \a notifyUser is true, then the message should be brought to the user's attention by various UI hints.
* If it is false, the message should appear in logs silently. Note that log viewer implementations may
* only respect notification hints for certain message levels.
*/
static void logMessage( const QString &message, const QString &tag = QString(), Qgis::MessageLevel level = Qgis::Warning, bool notifyUser = true );

signals:

/**
* Emitted whenever the log receives a \a message.
*
* This signal is emitted for all messages received by the log, regardless of the \a notifyUser flag's
* value for the message.
*/
void messageReceived( const QString &message, const QString &tag, Qgis::MessageLevel level );

//TODO QGIS 4.0 - remove received argument

/**
* Emitted whenever the log receives a message which has the \a notifyUser flag as true.
*
* If QgsMessageLogNotifyBlocker objects have been created then this signal may be
* temporarily suppressed.
* \see QgsMessageLogNotifyBlocker
*/
void messageReceived( bool received );

private:

void emitMessage( const QString &message, const QString &tag, Qgis::MessageLevel level );
void emitMessage( const QString &message, const QString &tag, Qgis::MessageLevel level, bool notifyUser = true );

int mAdviseBlockCount = 0;

friend class QgsMessageLogNotifyBlocker;

};

/**
* Temporarily blocks the application QgsMessageLog (see QgsApplication::messageLog()) from emitting the messageReceived( bool )
* signal for the lifetime of the object.
*
* Using this blocker allows messages to be logged without causing user interface hints flagging message log
* errors to be created.
*
* QgsMessageLogNotifyBlocker supports "stacked" blocking, so two QgsMessageLogNotifyBlocker created
* will both need to be destroyed before the messageReceived( bool ) signal is emitted again.
*
* \ingroup core
* \since QGIS 3.2
*/
class CORE_EXPORT QgsMessageLogNotifyBlocker
{
public:

/**
* Constructor for QgsMessageLogNotifyBlocker.
*
* This will block the log from emitting the messageReceived( bool ) signal for the lifetime of this object.
*/
QgsMessageLogNotifyBlocker();

//! QgsMessageLogNotifyBlocker cannot be copied
QgsMessageLogNotifyBlocker( const QgsMessageLogNotifyBlocker &other ) = delete;

//! QgsMessageLogNotifyBlocker cannot be copied
QgsMessageLogNotifyBlocker &operator=( const QgsMessageLogNotifyBlocker &other ) = delete;

~QgsMessageLogNotifyBlocker();

private:

#ifdef SIP_RUN
QgsMessageLogNotifyBlocker( const QgsMessageLogNotifyBlocker &other );
#endif
};

/**
Expand Down

0 comments on commit 949853a

Please sign in to comment.