Salome HOME
Join modifications from branch OCC_debug_for_3_2_0b1
[modules/gui.git] / src / LogWindow / LogWindow.cxx
1 //  KERNEL SALOME_Event : Define event posting mechanism
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
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. 
10 // 
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. 
15 // 
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 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21
22 #include "LogWindow.h"
23
24 #include <qfile.h>
25 #include <qlayout.h>
26 #include <qaction.h>
27 #include <qpopupmenu.h>
28 #include <qtextbrowser.h>
29 #include <qapplication.h>
30 #include <qdatetime.h>
31
32 #include <SUIT_Tools.h>
33 #include <SUIT_Session.h>
34 #include <SUIT_MessageBox.h>
35 #include <SUIT_ResourceMgr.h>
36
37 #define DEFAULT_SEPARATOR "***"
38
39 /*!
40   Converts rich text to plain text
41 */
42 static QString plainText( const QString& richText )
43 {
44   QString aText = richText;
45   int startTag = aText.find('<');
46   while ( 1 ) {
47     if ( startTag < 0 )
48       break;
49     int finishTag = aText.find('>',startTag);
50     if (finishTag < 0)
51       break;
52     aText = aText.remove(startTag, finishTag-startTag+1);
53     startTag = aText.find('<');
54   }
55   return aText;
56 }
57
58 /*!
59   Default constructor
60 */
61 LogWindow::LogWindow( QWidget* parent )
62 : QFrame( parent ),
63 SUIT_PopupClient()
64 {
65   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
66
67   QString fntSet = resMgr ? resMgr->stringValue( "Log Window", "font", QString::null ) : QString::null;
68
69   setFont( SUIT_Tools::stringToFont( fntSet ) );
70
71   myView = new QTextBrowser(this,"myView");
72 #if QT_VERSION>0x030007
73   myView->setTextFormat( Qt::LogText );
74 #endif
75   myView->viewport()->installEventFilter( this );
76
77   QVBoxLayout* main = new QVBoxLayout( this );
78   main->addWidget( myView );
79
80   myBannerSize = 0;
81   myBanner = "<b>Message Log</b>\n********************";
82   mySeparator = DEFAULT_SEPARATOR;
83
84   clear();
85
86   createActions();
87 }
88
89 /*!
90   Destructor
91 */
92 LogWindow::~LogWindow()
93 {
94 }
95
96 /*!
97   Custom event handler
98 */
99 bool LogWindow::eventFilter( QObject* o, QEvent* e )
100 {
101   if ( o == myView->viewport() && e->type() == QEvent::ContextMenu )
102   {
103     contextMenuRequest( (QContextMenuEvent*)e );
104     return true;
105   }
106   return QFrame::eventFilter( o, e );
107 }
108
109 /*!
110   Sets banner (title of message log)
111   \param banner - new title
112 */
113 void LogWindow::setBanner( const QString& banner )
114 {
115   myBanner = banner;
116
117   clear( false );
118 }
119
120 /*!
121   Set separator (line printing between messages)
122   \param separator - new separator
123 */
124 void LogWindow::setSeparator( const QString& separator )
125 {
126   mySeparator = separator;
127
128   clear( false );
129 }
130
131 /*!
132   Puts message to log window
133   \param message - text of message
134   \addSeparator - if it is true, then separator is added to tail of message log
135 */
136 void LogWindow::putMessage( const QString& message, bool addSeparator )
137 {
138   myView->append( message );
139   myHistory.append( plainText( message ) );
140
141   if ( addSeparator && !mySeparator.isNull() )
142   {
143     myView->append( mySeparator );   // add separator
144     myHistory.append( plainText( mySeparator ) );
145   }
146   myView->scrollToBottom();
147 }
148
149 /*!
150   Clears message log
151   \param clearHistory - if it is true, then also history is cleared
152 */
153 void LogWindow::clear( bool clearHistory )
154 {
155   myView->clear();
156   if ( clearHistory )
157     myHistory.clear();
158
159   if ( !myBanner.isEmpty() )
160   {
161     myView->append( myBanner );
162     myBannerSize = myView->paragraphs();
163   }
164   else
165     myBannerSize = 0;
166 }
167
168 /*!
169   Saves log to file
170   \param fileName - name of file
171 */
172 bool LogWindow::saveLog( const QString& fileName )
173 {
174   QFile file( fileName );
175   if ( !file.open( IO_WriteOnly ) )
176     return false;
177
178   QTextStream stream( &file );
179
180   stream << "*****************************************"   << endl;
181   stream << "Message Log"                                 << endl;
182   stream << QDate::currentDate().toString( "dd.MM:yyyy" ) << "  ";
183   stream << QTime::currentTime().toString( "hh:mm:ss" )   << endl;
184   stream << "*****************************************"   << endl;
185
186   for ( uint i = 0; i < myHistory.count(); i++ )
187     stream << myHistory[ i ] << endl;
188
189   file.close();
190   return true;
191 }
192
193 /*!
194   Creates actions
195 */
196 void LogWindow::createActions()
197 {
198   QAction* a = new QAction( "", tr( "&Copy" ), 0, this );
199   a->setStatusTip( tr( "&Copy" ) );
200   connect( a, SIGNAL( activated() ), SLOT( onCopy()));
201   myActions.insert( CopyId, a );
202
203   a = new QAction( "", tr( "Clea&r" ), 0, this );
204   a->setStatusTip( tr( "Clea&r" ) );
205   connect( a, SIGNAL( activated() ), SLOT( onClear()));
206   myActions.insert( ClearId, a );
207
208   a = new QAction( "", tr( "Select &All" ), 0, this );
209   a->setStatusTip( tr( "Select &All" ) );
210   connect( a, SIGNAL( activated() ), SLOT( onSelectAll()));
211   myActions.insert( SelectAllId, a );
212
213   a = new QAction( "", tr( "&Save log to file..." ), 0, this );
214   a->setStatusTip( tr( "&Save log to file..." ) );
215   connect( a, SIGNAL( activated() ), SLOT( onSaveToFile()));
216   myActions.insert( SaveToFileId, a );
217 }
218
219 /*!
220   Redefined virtual method for popup filling
221 */
222 void LogWindow::contextMenuPopup( QPopupMenu* popup )
223 {
224   myActions[ CopyId ]->addTo( popup );
225   myActions[ ClearId ]->addTo( popup );
226   
227   popup->insertSeparator();
228   
229   myActions[ SelectAllId ]->addTo( popup );
230   
231   popup->insertSeparator();
232   
233   myActions[ SaveToFileId ]->addTo( popup );
234
235   updateActions();
236 }
237
238 /*!
239   Updates enable status of actions
240 */
241 void LogWindow::updateActions()
242 {
243   int paraFrom, paraTo, indexFrom, indexTo;
244   myView->getSelection( &paraFrom, &indexFrom, &paraTo, &indexTo );
245   bool allSelected = myView->hasSelectedText() &&
246                      !paraFrom && paraTo == myView->paragraphs() - 1 && 
247                      !indexFrom && indexTo == myView->paragraphLength( paraTo );
248   myActions[ CopyId ]->setEnabled( myView->hasSelectedText() );
249   myActions[ ClearId ]->setEnabled( myView->paragraphs() > myBannerSize );
250   myActions[ SelectAllId ]->setEnabled( !allSelected );
251   myActions[ SaveToFileId ]->setEnabled( myHistory.count() > 0 );
252 }
253
254 /*!
255   SLOT: called if user click "Save" in popup
256 */
257 void LogWindow::onSaveToFile()
258 {
259   SUIT_Application* app = SUIT_Session::session()->activeApplication();
260   if ( !app )
261     return;
262
263   // call application-specific "Save file" dialog box
264   QString aName = app->getFileName( false, QString::null, QString( "*.log" ), QString::null, 0 );
265   if ( aName.isNull() )
266     return;
267
268   QApplication::setOverrideCursor( Qt::waitCursor );
269     
270   bool bOk = saveLog( aName );
271
272   QApplication::restoreOverrideCursor();
273
274   if ( !bOk )
275     SUIT_MessageBox::error1( this, tr( "Error" ), tr( "Can't save file" ), tr( "OK" ) );
276 }
277
278 /*!
279   SLOT: called if user click "Select all" in popup
280 */
281 void LogWindow::onSelectAll()
282 {
283   if ( myView )
284     myView->selectAll();
285 }
286
287 /*!
288   SLOT: called if user click "Clear" in popup
289 */
290 void LogWindow::onClear()
291 {
292   clear( false );
293 }
294
295 /*!
296   SLOT: called if user click "Copy" in popup
297 */
298 void LogWindow::onCopy()
299 {
300   if ( myView )
301     myView->copy();
302 }