QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsmessagelogviewer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmessagelogviewer.cpp - description
3 -------------------
4 begin : October 2011
5 copyright : (C) 2011 by Juergen E. Fischer
6 email : jef at norbit dot de
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsmessagelogviewer.h"
19
20#include "qgsapplication.h"
21#include "qgsmessagelog.h"
22#include "qgssettings.h"
23
24#include <QDateTime>
25#include <QDebug>
26#include <QDesktopServices>
27#include <QFile>
28#include <QPlainTextEdit>
29#include <QScrollBar>
30#include <QStatusBar>
31#include <QString>
32#include <QTableWidget>
33#include <QToolButton>
34#include <QToolTip>
35
36#include "moc_qgsmessagelogviewer.cpp"
37
38using namespace Qt::StringLiterals;
39
40QgsMessageLogViewer::QgsMessageLogViewer( QWidget *parent, Qt::WindowFlags fl )
41 : QDialog( parent, fl )
42{
43 setupUi( this );
44
45 connect(
47 static_cast<void ( QgsMessageLog::* )( const QString &, const QString &, Qgis::MessageLevel, Qgis::StringFormat )>( &QgsMessageLog::messageReceivedWithFormat ),
48 this,
49 static_cast<void ( QgsMessageLogViewer::* )( const QString &, const QString &, Qgis::MessageLevel, Qgis::StringFormat )>( &QgsMessageLogViewer::logMessage )
50 );
51
52 connect( tabWidget, &QTabWidget::tabCloseRequested, this, &QgsMessageLogViewer::closeTab );
53
54 connect( tabWidget, &QTabWidget::currentChanged, this, [this]( int index ) { tabWidget->setTabIcon( index, QIcon() ); } );
55
56 mTabBarContextMenu = new QMenu( this );
57 tabWidget->tabBar()->setContextMenuPolicy( Qt::CustomContextMenu );
58 connect( tabWidget->tabBar(), &QWidget::customContextMenuRequested, this, &QgsMessageLogViewer::showContextMenuForTabBar );
59}
60
61void QgsMessageLogViewer::showContextMenuForTabBar( QPoint point )
62{
63 if ( point.isNull() )
64 {
65 return;
66 }
67
68 mTabBarContextMenu->clear();
69
70 const int tabIndex = tabWidget->tabBar()->tabAt( point );
71
72 QAction *actionCloseTab = new QAction( tr( "Close Tab" ), mTabBarContextMenu );
73 connect( actionCloseTab, &QAction::triggered, this, [this, tabIndex] { closeTab( tabIndex ); } );
74 mTabBarContextMenu->addAction( actionCloseTab );
75
76 QAction *actionCloseOtherTabs = new QAction( tr( "Close Other Tabs" ), mTabBarContextMenu );
77 actionCloseOtherTabs->setEnabled( tabWidget->tabBar()->count() > 1 );
78 connect( actionCloseOtherTabs, &QAction::triggered, this, [this, tabIndex] {
79 int i;
80 for ( i = tabWidget->tabBar()->count() - 1; i >= 0; i-- )
81 {
82 if ( i != tabIndex )
83 {
84 closeTab( i );
85 }
86 }
87 } );
88 mTabBarContextMenu->addAction( actionCloseOtherTabs );
89
90 QAction *actionCloseAllTabs = new QAction( tr( "Close All Tabs" ), mTabBarContextMenu );
91 actionCloseAllTabs->setEnabled( tabWidget->tabBar()->count() > 0 );
92 connect( actionCloseAllTabs, &QAction::triggered, this, [this] {
93 int i;
94 for ( i = tabWidget->tabBar()->count() - 1; i >= 0; i-- )
95 {
96 closeTab( i );
97 }
98 } );
99 mTabBarContextMenu->addAction( actionCloseAllTabs );
100
101 mTabBarContextMenu->exec( tabWidget->tabBar()->mapToGlobal( point ) );
102}
103
105{
106 e->ignore();
107}
108
111
112void QgsMessageLogViewer::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level, Qgis::StringFormat format )
113{
114 constexpr int MESSAGE_COUNT_LIMIT = 10000;
115 // Avoid logging too many messages, which might blow memory.
116 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
117 return;
118 ++mMessageLoggedCount;
119
120 QString cleanedTag = tag;
121 if ( cleanedTag.isNull() )
122 cleanedTag = tr( "General" );
123
124 int i;
125 for ( i = 0; i < tabWidget->count() && tabWidget->tabText( i ).remove( QChar( '&' ) ) != cleanedTag; i++ )
126 ;
127
128 QPlainTextEdit *w = nullptr;
129 if ( i < tabWidget->count() )
130 {
131 w = qobject_cast<QPlainTextEdit *>( tabWidget->widget( i ) );
132 if ( i != tabWidget->currentIndex() )
133 {
134 tabWidget->setTabIcon( i, QgsApplication::getThemeIcon( u"mMessageLog.svg"_s ) );
135 }
136 }
137 else
138 {
139 w = new QPlainTextEdit( this );
140 w->setReadOnly( true );
141 w->viewport()->installEventFilter( this );
142 i = tabWidget->addTab( w, QgsApplication::getThemeIcon( u"mMessageLog.svg"_s ), cleanedTag );
143 }
144
145 QString levelString;
146 const QgsSettings settings;
147 const QPalette pal = qApp->palette();
148 const QString defaultColorName = pal.color( QPalette::WindowText ).name();
149 QString colorName;
150 switch ( level )
151 {
153 levelString = u"INFO"_s;
154 colorName = settings.value( u"colors/info"_s, QString() ).toString();
155 break;
157 levelString = u"WARNING"_s;
158 colorName = settings.value( u"colors/warning"_s, QString() ).toString();
159 break;
161 levelString = u"CRITICAL"_s;
162 colorName = settings.value( u"colors/critical"_s, QString() ).toString();
163 break;
165 levelString = u"SUCCESS"_s;
166 colorName = settings.value( u"colors/success"_s, QString() ).toString();
167 break;
169 levelString = u"NONE"_s;
170 colorName = settings.value( u"colors/default"_s, QString() ).toString();
171 break;
172 }
173 const QColor color = QColor( !colorName.isEmpty() ? colorName : defaultColorName );
174
175 const QString prefix = u"<font color=\"%1\">%2 &nbsp;&nbsp;&nbsp; %3 &nbsp;&nbsp;&nbsp;</font>"_s.arg( color.name(), QDateTime::currentDateTime().toString( Qt::ISODate ), levelString );
176 QString cleanedMessage;
177 switch ( format )
178 {
180 cleanedMessage = message.toHtmlEscaped();
181 break;
183 cleanedMessage = message;
184 break;
185 }
186 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
187 cleanedMessage = tr( "Message log truncated" );
188
189 cleanedMessage = cleanedMessage.prepend( prefix ).replace( '\n', "<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"_L1 );
190 w->appendHtml( cleanedMessage );
191 w->verticalScrollBar()->setValue( w->verticalScrollBar()->maximum() );
192 tabWidget->show();
193 emptyLabel->hide();
194}
195
196void QgsMessageLogViewer::showTab( const QString &tag )
197{
198 for ( int i = 0; i < tabWidget->count(); i++ )
199 {
200 if ( tabWidget->tabText( i ).remove( QChar( '&' ) ) == tag )
201 {
202 tabWidget->setCurrentIndex( i );
203 return;
204 }
205 }
206}
207
208void QgsMessageLogViewer::closeTab( int index )
209{
210 tabWidget->removeTab( index );
211 if ( tabWidget->count() == 0 )
212 {
213 tabWidget->hide();
214 emptyLabel->show();
215 }
216}
217
218bool QgsMessageLogViewer::eventFilter( QObject *object, QEvent *event )
219{
220 switch ( event->type() )
221 {
222 case QEvent::MouseButtonPress:
223 {
224 if ( QPlainTextEdit *te = qobject_cast<QPlainTextEdit *>( object->parent() ) )
225 {
226 QMouseEvent *me = static_cast<QMouseEvent *>( event );
227 mClickedAnchor = ( me->button() & Qt::LeftButton ) ? te->anchorAt( me->pos() ) : QString();
228 if ( !mClickedAnchor.isEmpty() )
229 return true;
230 }
231 break;
232 }
233
234 case QEvent::MouseButtonRelease:
235 {
236 if ( QPlainTextEdit *te = qobject_cast<QPlainTextEdit *>( object->parent() ) )
237 {
238 QMouseEvent *me = static_cast<QMouseEvent *>( event );
239 const QString clickedAnchor = ( me->button() & Qt::LeftButton ) ? te->anchorAt( me->pos() ) : QString();
240 if ( !clickedAnchor.isEmpty() && clickedAnchor == mClickedAnchor )
241 {
242 QDesktopServices::openUrl( mClickedAnchor );
243 return true;
244 }
245 }
246 break;
247 }
248
249 default:
250 break;
251 }
252
253 return QDialog::eventFilter( object, event );
254}
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition qgis.h:160
@ NoLevel
No level.
Definition qgis.h:165
@ Warning
Warning message.
Definition qgis.h:162
@ Critical
Critical/error message.
Definition qgis.h:163
@ Info
Information message.
Definition qgis.h:161
@ Success
Used for reporting a successful operation.
Definition qgis.h:164
StringFormat
Format of log message.
Definition qgis.h:175
@ Html
HTML message.
Definition qgis.h:177
@ PlainText
Text message.
Definition qgis.h:176
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsMessageLog * messageLog()
Returns the application's message log.
void closeEvent(QCloseEvent *e) override
bool eventFilter(QObject *obj, QEvent *ev) override
void logMessage(const QString &message, const QString &tag, Qgis::MessageLevel level, Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Logs a message to the viewer.
void showTab(const QString &tag)
Activates the tab whose title matches the given tag, if any.
QgsMessageLogViewer(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
Create a new message log viewer.
Interface for logging messages from QGIS in GUI independent way.
void messageReceivedWithFormat(const QString &message, const QString &tag, Qgis::MessageLevel level, Qgis::StringFormat)
Emitted whenever the log receives a message.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.