QGIS API Documentation 3.99.0-Master (26c88405ac0)
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 <QTableWidget>
32#include <QToolButton>
33#include <QToolTip>
34
35#include "moc_qgsmessagelogviewer.cpp"
36
37QgsMessageLogViewer::QgsMessageLogViewer( QWidget *parent, Qt::WindowFlags fl )
38 : QDialog( parent, fl )
39{
40 setupUi( this );
41
42 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 ) );
43
44 connect( tabWidget, &QTabWidget::tabCloseRequested, this, &QgsMessageLogViewer::closeTab );
45
46 connect( tabWidget, &QTabWidget::currentChanged, this, [this]( int index ) {
47 tabWidget->setTabIcon( index, QIcon() );
48 } );
49
50 mTabBarContextMenu = new QMenu( this );
51 tabWidget->tabBar()->setContextMenuPolicy( Qt::CustomContextMenu );
52 connect( tabWidget->tabBar(), &QWidget::customContextMenuRequested, this, &QgsMessageLogViewer::showContextMenuForTabBar );
53}
54
55void QgsMessageLogViewer::showContextMenuForTabBar( QPoint point )
56{
57 if ( point.isNull() )
58 {
59 return;
60 }
61
62 mTabBarContextMenu->clear();
63
64 const int tabIndex = tabWidget->tabBar()->tabAt( point );
65
66 QAction *actionCloseTab = new QAction( tr( "Close Tab" ), mTabBarContextMenu );
67 connect( actionCloseTab, &QAction::triggered, this, [this, tabIndex] {
68 closeTab( tabIndex );
69 } );
70 mTabBarContextMenu->addAction( actionCloseTab );
71
72 QAction *actionCloseOtherTabs = new QAction( tr( "Close Other Tabs" ), mTabBarContextMenu );
73 actionCloseOtherTabs->setEnabled( tabWidget->tabBar()->count() > 1 );
74 connect( actionCloseOtherTabs, &QAction::triggered, this, [this, tabIndex] {
75 int i;
76 for ( i = tabWidget->tabBar()->count() - 1; i >= 0; i-- )
77 {
78 if ( i != tabIndex )
79 {
80 closeTab( i );
81 }
82 }
83 } );
84 mTabBarContextMenu->addAction( actionCloseOtherTabs );
85
86 QAction *actionCloseAllTabs = new QAction( tr( "Close All Tabs" ), mTabBarContextMenu );
87 actionCloseAllTabs->setEnabled( tabWidget->tabBar()->count() > 0 );
88 connect( actionCloseAllTabs, &QAction::triggered, this, [this] {
89 int i;
90 for ( i = tabWidget->tabBar()->count() - 1; i >= 0; i-- )
91 {
92 closeTab( i );
93 }
94 } );
95 mTabBarContextMenu->addAction( actionCloseAllTabs );
96
97 mTabBarContextMenu->exec( tabWidget->tabBar()->mapToGlobal( point ) );
98}
99
101{
102 e->ignore();
103}
104
108
109void QgsMessageLogViewer::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
110{
111 constexpr int MESSAGE_COUNT_LIMIT = 10000;
112 // Avoid logging too many messages, which might blow memory.
113 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
114 return;
115 ++mMessageLoggedCount;
116
117 QString cleanedTag = tag;
118 if ( cleanedTag.isNull() )
119 cleanedTag = tr( "General" );
120
121 int i;
122 for ( i = 0; i < tabWidget->count() && tabWidget->tabText( i ).remove( QChar( '&' ) ) != cleanedTag; i++ )
123 ;
124
125 QPlainTextEdit *w = nullptr;
126 if ( i < tabWidget->count() )
127 {
128 w = qobject_cast<QPlainTextEdit *>( tabWidget->widget( i ) );
129 if ( i != tabWidget->currentIndex() )
130 {
131 tabWidget->setTabIcon( i, QgsApplication::getThemeIcon( QStringLiteral( "mMessageLog.svg" ) ) );
132 }
133 }
134 else
135 {
136 w = new QPlainTextEdit( this );
137 w->setReadOnly( true );
138 w->viewport()->installEventFilter( this );
139 i = tabWidget->addTab( w, QgsApplication::getThemeIcon( QStringLiteral( "mMessageLog.svg" ) ), cleanedTag );
140 }
141
142 QString levelString;
143 const QgsSettings settings;
144 const QPalette pal = qApp->palette();
145 const QString defaultColorName = pal.color( QPalette::WindowText ).name();
146 QString colorName;
147 switch ( level )
148 {
150 levelString = QStringLiteral( "INFO" );
151 colorName = settings.value( QStringLiteral( "colors/info" ), QString() ).toString();
152 break;
154 levelString = QStringLiteral( "WARNING" );
155 colorName = settings.value( QStringLiteral( "colors/warning" ), QString() ).toString();
156 break;
158 levelString = QStringLiteral( "CRITICAL" );
159 colorName = settings.value( QStringLiteral( "colors/critical" ), QString() ).toString();
160 break;
162 levelString = QStringLiteral( "SUCCESS" );
163 colorName = settings.value( QStringLiteral( "colors/success" ), QString() ).toString();
164 break;
166 levelString = QStringLiteral( "NONE" );
167 colorName = settings.value( QStringLiteral( "colors/default" ), QString() ).toString();
168 break;
169 }
170 const QColor color = QColor( !colorName.isEmpty() ? colorName : defaultColorName );
171
172 const QString prefix = QStringLiteral( "<font color=\"%1\">%2 &nbsp;&nbsp;&nbsp; %3 &nbsp;&nbsp;&nbsp;</font>" )
173 .arg( color.name(), QDateTime::currentDateTime().toString( Qt::ISODate ), levelString );
174 QString cleanedMessage = message.toHtmlEscaped();
175 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
176 cleanedMessage = tr( "Message log truncated" );
177
178 cleanedMessage = cleanedMessage.prepend( prefix ).replace( '\n', QLatin1String( "<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;" ) );
179 w->appendHtml( cleanedMessage );
180 w->verticalScrollBar()->setValue( w->verticalScrollBar()->maximum() );
181 tabWidget->show();
182 emptyLabel->hide();
183}
184
185void QgsMessageLogViewer::showTab( const QString &tag )
186{
187 for ( int i = 0; i < tabWidget->count(); i++ )
188 {
189 if ( tabWidget->tabText( i ).remove( QChar( '&' ) ) == tag )
190 {
191 tabWidget->setCurrentIndex( i );
192 return;
193 }
194 }
195}
196
197void QgsMessageLogViewer::closeTab( int index )
198{
199 tabWidget->removeTab( index );
200 if ( tabWidget->count() == 0 )
201 {
202 tabWidget->hide();
203 emptyLabel->show();
204 }
205}
206
207bool QgsMessageLogViewer::eventFilter( QObject *object, QEvent *event )
208{
209 switch ( event->type() )
210 {
211 case QEvent::MouseButtonPress:
212 {
213 if ( QPlainTextEdit *te = qobject_cast<QPlainTextEdit *>( object->parent() ) )
214 {
215 QMouseEvent *me = static_cast<QMouseEvent *>( event );
216 mClickedAnchor = ( me->button() & Qt::LeftButton ) ? te->anchorAt( me->pos() ) : QString();
217 if ( !mClickedAnchor.isEmpty() )
218 return true;
219 }
220 break;
221 }
222
223 case QEvent::MouseButtonRelease:
224 {
225 if ( QPlainTextEdit *te = qobject_cast<QPlainTextEdit *>( object->parent() ) )
226 {
227 QMouseEvent *me = static_cast<QMouseEvent *>( event );
228 const QString clickedAnchor = ( me->button() & Qt::LeftButton ) ? te->anchorAt( me->pos() ) : QString();
229 if ( !clickedAnchor.isEmpty() && clickedAnchor == mClickedAnchor )
230 {
231 QDesktopServices::openUrl( mClickedAnchor );
232 return true;
233 }
234 }
235 break;
236 }
237
238 default:
239 break;
240 }
241
242 return QDialog::eventFilter( object, event );
243}
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition qgis.h:156
@ NoLevel
No level.
Definition qgis.h:161
@ Warning
Warning message.
Definition qgis.h:158
@ Critical
Critical/error message.
Definition qgis.h:159
@ Info
Information message.
Definition qgis.h:157
@ Success
Used for reporting a successful operation.
Definition qgis.h:160
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:65
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.