1 // Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // KERNEL SALOME_Event : Define event posting mechanism
24 // File : LogWindow.cxx
25 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
27 #include "LogWindow.h"
30 #include <QApplication>
36 #include <QTextStream>
38 #include <QVBoxLayout>
40 #include <SUIT_MessageBox.h>
41 #include <SUIT_ResourceMgr.h>
42 #include <SUIT_Session.h>
43 #include <SUIT_Tools.h>
45 #define DEFAULT_SEPARATOR "***"
50 \brief Convert rich text to plain text.
52 \param richText rich text string
53 \return converted plain text string
55 QString plainText( const QString& richText )
57 QString aText = richText;
58 int startTag = aText.indexOf( '<' );
64 int finishTag = aText.indexOf( '>', startTag );
68 aText = aText.remove( startTag, finishTag - startTag + 1 );
69 startTag = aText.indexOf( '<' );
77 \brief Widget, displaying log messages.
79 The log messages window provides operations like:
81 - display timestamps at the message beginning
82 - color messages according to their purposes (e.g., errors/warning)
84 - copy messages to clipvoard
85 - save message log to to the text file
91 Creates new messages log window widget.
92 \param parent parent widget
94 LogWindow::LogWindow( QWidget* parent )
95 : QWidget( parent ), SUIT_PopupClient(), QtxMsgHandlerCallback( false )
97 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
99 QString fntSet = resMgr ? resMgr->stringValue( "Log Window", "font", QString() ) : QString();
101 setFont( SUIT_Tools::stringToFont( fntSet ) );
103 myView = new QTextEdit( this );
104 myView->setReadOnly( true );
105 myView->viewport()->installEventFilter( this );
106 myView->setPlaceholderText( "Message Log" );
108 QVBoxLayout* main = new QVBoxLayout( this );
109 main->setMargin( 0 );
110 main->addWidget( myView );
112 mySeparator = DEFAULT_SEPARATOR;
122 Does nothing for the moment.
124 LogWindow::~LogWindow()
129 \brief Get current banner (text shown when log window is empty).
130 \return string representing the current banner
132 QString LogWindow::banner() const
134 return myView->placeholderText();
138 \brief Get current separator (text which is printed between messages).
139 \return string representing the current separator
141 QString LogWindow::separator() const
147 \brief Set current banner (text shown when log window is empty).
148 \param banner new banner
150 void LogWindow::setBanner( const QString& banner )
152 myView->setPlaceholderText( banner );
156 Set current separator (text which is printed between messages).
157 \param separator new separator
159 void LogWindow::setSeparator( const QString& separator )
161 mySeparator = separator;
167 \brief Custom event handler.
169 Process context popup menu request event.
173 \return True if the event is processed and further processing should be stopped
175 bool LogWindow::eventFilter( QObject* o, QEvent* e )
177 if ( o == myView->viewport() && e->type() == QEvent::ContextMenu )
179 contextMenuRequest( (QContextMenuEvent*)e );
182 return QWidget::eventFilter( o, e );
186 \brief Put new message to the log window.
187 \param message text of the message
188 \param flags ORed flags which define how the message should be printed
190 void LogWindow::putMessage( const QString& message, const int flags )
192 putMessage( message, QColor(), flags );
196 \brief Put new message to the log window.
197 \param message text of the message
198 \param color text color of the message
199 \param flags ORed flags which define how the message should be printed
201 void LogWindow::putMessage( const QString& message, const QColor& color, const int flags )
203 QString msg = message;
207 bool noColor = flags & DisplayNoColor;
209 if ( color.isValid() )
210 msg = QString( "<font color=\"%1\">%2</font>" ).arg( color.name() ).arg( msg );
213 if ( flags & DisplayDate )
215 dStr = QDate::currentDate().toString( Qt::SystemLocaleDate );
217 dStr = QString( "<font color=\"#003380\">%1</font>" ).arg( dStr );
221 if ( flags & DisplayTime )
223 tStr = QTime::currentTime().toString( Qt::SystemLocaleDate );
225 tStr = QString( "<font color=\"#008033\">%1</font>" ).arg( tStr );
228 QString dateTime = QString( "%1 %2" ).arg( dStr ).arg( tStr ).trimmed();
229 if ( !dateTime.isEmpty() )
230 msg = QString( "[%1] %2" ).arg( dateTime ).arg( msg );
233 myHistory.append( plainText( message ) );
235 if ( flags & DisplaySeparator && !mySeparator.isEmpty() )
238 append( mySeparator );
239 myHistory.append( plainText( mySeparator ) );
241 myView->moveCursor( QTextCursor::End );
245 \brief Append text to the log window.
246 \param text Text being added.
248 void LogWindow::append( const QString text )
250 if ( !text.isEmpty() )
252 myView->append( text );
253 QTextBlock block = myView->document()->lastBlock();
254 QTextCursor cursor( block );
255 QTextBlockFormat format = cursor.blockFormat();
256 format.setBottomMargin( 10 );
257 cursor.setBlockFormat( format );
262 \brief Clear message log.
263 \param clearHistory if True, clear also the messages history
265 void LogWindow::clear( bool clearHistory )
273 \brief Save messages log to the file.
274 \param fileName name of the file
275 \return \c true on success and \c false on error
277 bool LogWindow::saveLog( const QString& fileName )
279 QFile file( fileName );
280 if ( !file.open( QFile::WriteOnly ) )
283 QTextStream stream( &file );
285 stream << "*****************************************" << endl;
286 stream << "Message Log" << endl;
287 stream << QDate::currentDate().toString( "dd.MM:yyyy" ) << " ";
288 stream << QTime::currentTime().toString( "hh:mm:ss" ) << endl;
289 stream << "*****************************************" << endl;
291 for ( int i = 0; i < myHistory.count(); i++ )
292 stream << myHistory[ i ] << endl;
299 \brief Create context popup menu actions.
301 void LogWindow::createActions()
303 QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
304 a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
305 connect( a, SIGNAL( triggered( bool ) ), SLOT( onCopy() ) );
306 myActions.insert( CopyId, a );
308 a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
309 a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
310 connect( a, SIGNAL( triggered( bool ) ), SLOT( onClear() ) );
311 myActions.insert( ClearId, a );
313 a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
314 a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
315 connect( a, SIGNAL( triggered( bool ) ), SLOT( onSelectAll() ) );
316 myActions.insert( SelectAllId, a );
318 a = new QAction( tr( "EDIT_SAVETOFILE_CMD" ), this );
319 a->setStatusTip( tr( "EDIT_SAVETOFILE_CMD" ) );
320 connect( a, SIGNAL( triggered( bool ) ), SLOT( onSaveToFile() ) );
321 myActions.insert( SaveToFileId, a );
325 \brief Create the context popup menu.
327 Fill in the popup menu with the commands.
329 \param menu context popup menu
331 void LogWindow::contextMenuPopup( QMenu* popup )
333 popup->addAction( myActions[ CopyId ] );
334 popup->addAction( myActions[ ClearId ] );
335 popup->addSeparator();
336 popup->addAction( myActions[ SelectAllId ] );
337 popup->addSeparator();
338 popup->addAction( myActions[ SaveToFileId ] );
340 Qtx::simplifySeparators( popup );
346 \brief Update menu actions.
348 Update context popup menu action state.
350 void LogWindow::updateActions()
352 myActions[CopyId]->setEnabled( myView->textCursor().hasSelection() );
353 myActions[ ClearId ]->setEnabled( !myView->document()->isEmpty() );
354 myActions[SelectAllId]->setEnabled( !myView->document()->isEmpty() );
355 myActions[ SaveToFileId ]->setEnabled( myHistory.count() > 0 );
359 \brief Called when user selects "Save To File" command in the popup menu.
361 void LogWindow::onSaveToFile()
363 SUIT_Application* app = SUIT_Session::session()->activeApplication();
367 // call application-specific "Save file" dialog box
368 QString aName = app->getFileName( false, QString(), QString( "*.log" ), QString(), 0 );
369 if ( aName.isNull() )
372 QApplication::setOverrideCursor( Qt::WaitCursor );
374 bool bOk = saveLog( aName );
376 QApplication::restoreOverrideCursor();
379 SUIT_MessageBox::critical( this, tr( "ERR_ERROR" ), tr( "ERR_CANT_SAVE_FILE" ) );
383 \brief Called when user selects "Select all" command in the popup menu.
385 void LogWindow::onSelectAll()
392 \brief Called when user click "Clear" command in the popup menu.
394 void LogWindow::onClear()
400 \brief Called when user click "Copy" command in the popup menu.
402 void LogWindow::onCopy()
409 \brief Set actions to be visible in the context popup menu.
411 Actions, which IDs are set in \a flags parameter, will be shown in the
412 context popup menu. Other actions will not be shown.
414 \param flags ORed together actions flags
416 void LogWindow::setMenuActions( const int flags )
418 myActions[CopyId]->setVisible( flags & CopyId );
419 myActions[ClearId]->setVisible( flags & ClearId );
420 myActions[SelectAllId]->setVisible( flags & SelectAllId );
421 myActions[SaveToFileId]->setVisible( flags & SaveToFileId );
425 \brief Get menu actions which are currently visible in the context popup menu.
426 \return ORed together actions flags
429 int LogWindow::menuActions() const
432 ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
433 ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
434 ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
435 ret = ret | ( myActions[SaveToFileId]->isVisible() ? SaveToFileId : 0 );
440 \brief Activate/deactivate Qt messages handling.
441 \param on If \c true, Qt messags are handled by log window.
443 void LogWindow::handleQtMessages(bool on)
452 \brief Handle Qt messages.
453 \param type Qt message type.
454 \param context Message context.
455 \param message Message text.
457 void LogWindow::qtMessage( QtMsgType type, const QMessageLogContext&, const QString& message )
463 color = QColor("#008000"); // dark green
466 color = QColor("#ff0000"); // red
469 color = QColor("#800000"); // dark red
472 color = QColor("#ff9000"); // orange
476 color = QColor("#000000"); // black
479 putMessage( message, color, DisplayNormal);
483 \fn virtual QString LogWindow::popupClientType() const;
484 \brief Get popup client symbolic name, used in popup menu management system.
485 \return symbolic name