1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, 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>
35 #include <QTextStream>
37 #include <QVBoxLayout>
39 #include <SUIT_MessageBox.h>
40 #include <SUIT_ResourceMgr.h>
41 #include <SUIT_Session.h>
42 #include <SUIT_Tools.h>
44 #define DEFAULT_SEPARATOR "***"
47 \brief Convert rich text to plain text.
49 \param richText rich text string
50 \return converted plain text string
52 static QString plainText( const QString& richText )
54 QString aText = richText;
55 int startTag = aText.indexOf( '<' );
61 int finishTag = aText.indexOf( '>', startTag );
65 aText = aText.remove( startTag, finishTag - startTag + 1 );
66 startTag = aText.indexOf( '<' );
73 \brief Widget, displaying log messages.
75 The log messages window provides operations like:
77 - display timestamps at the message beginning
78 - color messages according to their purposes (e.g., errors/warning)
80 - copy messages to clipvoard
81 - save message log to to the text file
87 Creates new messages log window widget.
88 \param parent parent widget
90 LogWindow::LogWindow( QWidget* parent )
94 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
96 QString fntSet = resMgr ? resMgr->stringValue( "Log Window", "font", QString() ) : QString();
98 setFont( SUIT_Tools::stringToFont( fntSet ) );
100 myView = new QTextEdit( this );
101 myView->setReadOnly( true );
102 myView->viewport()->installEventFilter( this );
104 QVBoxLayout* main = new QVBoxLayout( this );
105 main->setMargin( 0 );
106 main->addWidget( myView );
109 myBanner = "<b>Message Log</b>\n********************";
110 mySeparator = DEFAULT_SEPARATOR;
120 Does nothing for the moment.
122 LogWindow::~LogWindow()
127 \brief Get current banner (message log window header text).
128 \return string representing the current banner
130 QString LogWindow::banner() const
136 \brief Get current separator (text which is printed between messages).
137 \return string representing the current separator
139 QString LogWindow::separator() const
145 \brief Set current banner (message log window header text).
146 \param banner new banner
148 void LogWindow::setBanner( const QString& 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 );
232 myView->append( msg );
233 myHistory.append( plainText( message ) );
235 if ( flags & DisplaySeparator && !mySeparator.isEmpty() )
237 myView->append( mySeparator ); // add separator
238 myHistory.append( plainText( mySeparator ) );
240 myView->moveCursor( QTextCursor::End );
244 \brief Clear message log.
245 \param clearHistory if True, clear also the messages history
247 void LogWindow::clear( bool clearHistory )
253 if ( !myBanner.isEmpty() )
255 myView->append( myBanner );
256 myBannerSize = myView->document()->blockCount();
263 \brief Save messages log to the file.
264 \param fileName name of the file
265 \return \c true on success and \c false on error
267 bool LogWindow::saveLog( const QString& fileName )
269 QFile file( fileName );
270 if ( !file.open( QFile::WriteOnly ) )
273 QTextStream stream( &file );
275 stream << "*****************************************" << endl;
276 stream << "Message Log" << endl;
277 stream << QDate::currentDate().toString( "dd.MM:yyyy" ) << " ";
278 stream << QTime::currentTime().toString( "hh:mm:ss" ) << endl;
279 stream << "*****************************************" << endl;
281 for ( int i = 0; i < myHistory.count(); i++ )
282 stream << myHistory[ i ] << endl;
289 \brief Create context popup menu actions.
291 void LogWindow::createActions()
293 QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
294 a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
295 connect( a, SIGNAL( triggered( bool ) ), SLOT( onCopy() ) );
296 myActions.insert( CopyId, a );
298 a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
299 a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
300 connect( a, SIGNAL( triggered( bool ) ), SLOT( onClear() ) );
301 myActions.insert( ClearId, a );
303 a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
304 a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
305 connect( a, SIGNAL( triggered( bool ) ), SLOT( onSelectAll() ) );
306 myActions.insert( SelectAllId, a );
308 a = new QAction( tr( "EDIT_SAVETOFILE_CMD" ), this );
309 a->setStatusTip( tr( "EDIT_SAVETOFILE_CMD" ) );
310 connect( a, SIGNAL( triggered( bool ) ), SLOT( onSaveToFile() ) );
311 myActions.insert( SaveToFileId, a );
315 \brief Create the context popup menu.
317 Fill in the popup menu with the commands.
319 \param menu context popup menu
321 void LogWindow::contextMenuPopup( QMenu* popup )
323 popup->addAction( myActions[ CopyId ] );
324 popup->addAction( myActions[ ClearId ] );
325 popup->addSeparator();
326 popup->addAction( myActions[ SelectAllId ] );
327 popup->addSeparator();
328 popup->addAction( myActions[ SaveToFileId ] );
330 Qtx::simplifySeparators( popup );
336 \brief Update menu actions.
338 Update context popup menu action state.
340 void LogWindow::updateActions()
342 myActions[CopyId]->setEnabled( myView->textCursor().hasSelection() );
343 myActions[ ClearId ]->setEnabled( myView->document()->blockCount() > myBannerSize );
344 myActions[SelectAllId]->setEnabled( !myView->document()->isEmpty() );
345 myActions[ SaveToFileId ]->setEnabled( myHistory.count() > 0 );
349 \brief Called when user selects "Save To File" command in the popup menu.
351 void LogWindow::onSaveToFile()
353 SUIT_Application* app = SUIT_Session::session()->activeApplication();
357 // call application-specific "Save file" dialog box
358 QString aName = app->getFileName( false, QString(), QString( "*.log" ), QString(), 0 );
359 if ( aName.isNull() )
362 QApplication::setOverrideCursor( Qt::WaitCursor );
364 bool bOk = saveLog( aName );
366 QApplication::restoreOverrideCursor();
369 SUIT_MessageBox::critical( this, tr( "ERR_ERROR" ), tr( "ERR_CANT_SAVE_FILE" ) );
373 \brief Called when user selects "Select all" command in the popup menu.
375 void LogWindow::onSelectAll()
382 \brief Called when user click "Clear" command in the popup menu.
384 void LogWindow::onClear()
390 \brief Called when user click "Copy" command in the popup menu.
392 void LogWindow::onCopy()
399 \brief Set actions to be visible in the context popup menu.
401 Actions, which IDs are set in \a flags parameter, will be shown in the
402 context popup menu. Other actions will not be shown.
404 \param flags ORed together actions flags
406 void LogWindow::setMenuActions( const int flags )
408 myActions[CopyId]->setVisible( flags & CopyId );
409 myActions[ClearId]->setVisible( flags & ClearId );
410 myActions[SelectAllId]->setVisible( flags & SelectAllId );
411 myActions[SaveToFileId]->setVisible( flags & SaveToFileId );
415 \brief Get menu actions which are currently visible in the context popup menu.
416 \return ORed together actions flags
419 int LogWindow::menuActions() const
422 ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
423 ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
424 ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
425 ret = ret | ( myActions[SaveToFileId]->isVisible() ? SaveToFileId : 0 );
430 \fn virtual QString LogWindow::popupClientType() const;
431 \brief Get popup client symbolic name, used in popup menu management system.
432 \return symbolic name