QGIS API Documentation 3.99.0-Master (d270888f95f)
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( QgsApplication::messageLog(), static_cast<void ( QgsMessageLog::* )( const QString &, const QString &, Qgis::MessageLevel )>( &QgsMessageLog::messageReceived ), this, static_cast<void ( QgsMessageLogViewer::* )( const QString &, const QString &, Qgis::MessageLevel )>( &QgsMessageLogViewer::logMessage ) );
46
47 connect( tabWidget, &QTabWidget::tabCloseRequested, this, &QgsMessageLogViewer::closeTab );
48
49 connect( tabWidget, &QTabWidget::currentChanged, this, [this]( int index ) {
50 tabWidget->setTabIcon( index, QIcon() );
51 } );
52
53 mTabBarContextMenu = new QMenu( this );
54 tabWidget->tabBar()->setContextMenuPolicy( Qt::CustomContextMenu );
55 connect( tabWidget->tabBar(), &QWidget::customContextMenuRequested, this, &QgsMessageLogViewer::showContextMenuForTabBar );
56}
57
58void QgsMessageLogViewer::showContextMenuForTabBar( QPoint point )
59{
60 if ( point.isNull() )
61 {
62 return;
63 }
64
65 mTabBarContextMenu->clear();
66
67 const int tabIndex = tabWidget->tabBar()->tabAt( point );
68
69 QAction *actionCloseTab = new QAction( tr( "Close Tab" ), mTabBarContextMenu );
70 connect( actionCloseTab, &QAction::triggered, this, [this, tabIndex] {
71 closeTab( tabIndex );
72 } );
73 mTabBarContextMenu->addAction( actionCloseTab );
74
75 QAction *actionCloseOtherTabs = new QAction( tr( "Close Other Tabs" ), mTabBarContextMenu );
76 actionCloseOtherTabs->setEnabled( tabWidget->tabBar()->count() > 1 );
77 connect( actionCloseOtherTabs, &QAction::triggered, this, [this, tabIndex] {
78 int i;
79 for ( i = tabWidget->tabBar()->count() - 1; i >= 0; i-- )
80 {
81 if ( i != tabIndex )
82 {
83 closeTab( i );
84 }
85 }
86 } );
87 mTabBarContextMenu->addAction( actionCloseOtherTabs );
88
89 QAction *actionCloseAllTabs = new QAction( tr( "Close All Tabs" ), mTabBarContextMenu );
90 actionCloseAllTabs->setEnabled( tabWidget->tabBar()->count() > 0 );
91 connect( actionCloseAllTabs, &QAction::triggered, this, [this] {
92 int i;
93 for ( i = tabWidget->tabBar()->count() - 1; i >= 0; i-- )
94 {
95 closeTab( i );
96 }
97 } );
98 mTabBarContextMenu->addAction( actionCloseAllTabs );
99
100 mTabBarContextMenu->exec( tabWidget->tabBar()->mapToGlobal( point ) );
101}
102
104{
105 e->ignore();
106}
107
111
112void QgsMessageLogViewer::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
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
176 .arg( color.name(), QDateTime::currentDateTime().toString( Qt::ISODate ), levelString );
177 QString cleanedMessage = message.toHtmlEscaped();
178 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
179 cleanedMessage = tr( "Message log truncated" );
180
181 cleanedMessage = cleanedMessage.prepend( prefix ).replace( '\n', "<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"_L1 );
182 w->appendHtml( cleanedMessage );
183 w->verticalScrollBar()->setValue( w->verticalScrollBar()->maximum() );
184 tabWidget->show();
185 emptyLabel->hide();
186}
187
188void QgsMessageLogViewer::showTab( const QString &tag )
189{
190 for ( int i = 0; i < tabWidget->count(); i++ )
191 {
192 if ( tabWidget->tabText( i ).remove( QChar( '&' ) ) == tag )
193 {
194 tabWidget->setCurrentIndex( i );
195 return;
196 }
197 }
198}
199
200void QgsMessageLogViewer::closeTab( int index )
201{
202 tabWidget->removeTab( index );
203 if ( tabWidget->count() == 0 )
204 {
205 tabWidget->hide();
206 emptyLabel->show();
207 }
208}
209
210bool QgsMessageLogViewer::eventFilter( QObject *object, QEvent *event )
211{
212 switch ( event->type() )
213 {
214 case QEvent::MouseButtonPress:
215 {
216 if ( QPlainTextEdit *te = qobject_cast<QPlainTextEdit *>( object->parent() ) )
217 {
218 QMouseEvent *me = static_cast<QMouseEvent *>( event );
219 mClickedAnchor = ( me->button() & Qt::LeftButton ) ? te->anchorAt( me->pos() ) : QString();
220 if ( !mClickedAnchor.isEmpty() )
221 return true;
222 }
223 break;
224 }
225
226 case QEvent::MouseButtonRelease:
227 {
228 if ( QPlainTextEdit *te = qobject_cast<QPlainTextEdit *>( object->parent() ) )
229 {
230 QMouseEvent *me = static_cast<QMouseEvent *>( event );
231 const QString clickedAnchor = ( me->button() & Qt::LeftButton ) ? te->anchorAt( me->pos() ) : QString();
232 if ( !clickedAnchor.isEmpty() && clickedAnchor == mClickedAnchor )
233 {
234 QDesktopServices::openUrl( mClickedAnchor );
235 return true;
236 }
237 }
238 break;
239 }
240
241 default:
242 break;
243 }
244
245 return QDialog::eventFilter( object, event );
246}
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition qgis.h:159
@ NoLevel
No level.
Definition qgis.h:164
@ Warning
Warning message.
Definition qgis.h:161
@ Critical
Critical/error message.
Definition qgis.h:162
@ Info
Information message.
Definition qgis.h:160
@ Success
Used for reporting a successful operation.
Definition qgis.h:163
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 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.
void logMessage(const QString &message, const QString &tag, Qgis::MessageLevel level)
Logs a message to the viewer.
Interface for logging messages from QGIS in GUI independent way.
void messageReceived(const QString &message, const QString &tag, Qgis::MessageLevel level)
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.