]> SALOME platform Git repositories - modules/gui.git/blob - src/SalomeApp/SalomeApp_NoteBook.cxx
Salome HOME
According to cotech80 PyConsoleBase->PyConsole and PyConsole->SalomePyConsole
[modules/gui.git] / src / SalomeApp / SalomeApp_NoteBook.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File:    SalomeApp_NoteBook.cxx
21 // Author : Roman NIKOLAEV, Open CASCADE S.A.S.
22 // Module : GUI
23 //
24 #include "PyConsole_Interp.h" // this include must be first (see PyInterp_base.h)!
25 #include "SalomePyConsole_Console.h"
26
27 #include "SalomeApp_NoteBook.h"
28 #include "SalomeApp_Application.h"
29 #include "SalomeApp_Study.h"
30 #include "SalomeApp_VisualState.h"
31
32 #include <Qtx.h>
33
34 #include <CAM_Module.h>
35
36 #include <SUIT_Desktop.h>
37 #include <SUIT_MessageBox.h>
38 #include <SUIT_ResourceMgr.h>
39 #include <SUIT_Session.h>
40
41 #include <QWidget>
42 #include <QGridLayout>
43 #include <QTableWidget>
44 #include <QTableWidgetItem>
45 #include <QPushButton>
46 #include <QFont>
47 #include <QGroupBox>
48 #include <QList>
49 #include <QApplication>
50 #include <QDir>
51
52 #include <string>
53 #include <vector>
54
55 #define DEFAULT_MARGIN  11
56 #define DEFAULT_SPACING 6
57 #define SPACER_SIZE     100
58 #define COLUMN_SIZE     100
59
60 #define NAME_COLUMN  0
61 #define VALUE_COLUMN 1
62
63
64 ///////////////////////////////////////////////////////////////////////////
65 //                 NoteBook_TableRow class                               //
66 ///////////////////////////////////////////////////////////////////////////
67 //============================================================================
68 /*! Function : NoteBook_TableRow
69  *  Purpose  : Constructor
70  */
71 //============================================================================
72 NoteBook_TableRow::NoteBook_TableRow(int index, NoteBook_Table* parentTable, QWidget* parent):
73   QWidget(parent),
74   myParentTable(parentTable),
75   myIndex(index),
76   myRowHeader(new QTableWidgetItem()),
77   myVariableName(new QTableWidgetItem()),
78   myVariableValue(new QTableWidgetItem())
79 {
80 }
81
82 //============================================================================
83 /*! Function : ~NoteBook_TableRow
84  *  Purpose  : Destructor
85  */
86 //============================================================================
87 NoteBook_TableRow::~NoteBook_TableRow()
88 {
89 }
90
91 //============================================================================
92 /*! Function : AddToTable
93  *  Purpose  : Add this row to the table theTable
94  */
95 //============================================================================
96 void NoteBook_TableRow::AddToTable(QTableWidget *theTable)
97 {
98   int aPosition = theTable->rowCount();
99   int aRowCount = aPosition+1;
100   theTable->setRowCount(aRowCount);
101   myRowHeader->setText(QString::number(aRowCount));
102
103   theTable->setVerticalHeaderItem(aPosition,myRowHeader);
104   theTable->setItem(aPosition, NAME_COLUMN, myVariableName);
105   theTable->setItem(aPosition, VALUE_COLUMN, myVariableValue);
106 }
107
108 //============================================================================
109 /*! Function : SetName
110  *  Purpose  : 
111  */
112 //============================================================================
113 void NoteBook_TableRow::SetName(const QString theName)
114 {
115   myVariableName->setText(theName);
116 }
117
118 //============================================================================
119 /*! Function : SetValue
120  *  Purpose  : 
121  */
122 //============================================================================
123 void NoteBook_TableRow::SetValue(const QString theValue)
124 {
125   myVariableValue->setText(theValue);
126 }
127
128 //============================================================================
129 /*! Function : GetName
130  *  Purpose  : Return variable name
131  */
132 //============================================================================
133 QString NoteBook_TableRow::GetName() const
134 {
135   return myVariableName->text();
136 }
137
138 //============================================================================
139 /*! Function : GetValue
140  *  Purpose  : Return variable value
141  */
142 //============================================================================
143 QString NoteBook_TableRow::GetValue() const
144 {
145   return myVariableValue->text(); 
146 }
147
148 //============================================================================
149 /*! Function : CheckName
150  *  Purpose  : Return true if variable name correct, otherwise return false
151  */
152 //============================================================================
153 bool NoteBook_TableRow::CheckName()
154 {
155   QString aName = GetName();
156   int aPos = 0;
157   QRegExpValidator aValidator( QRegExp("^([a-zA-Z]+)([a-zA-Z0-9_]*)$"), 0 );
158   if( aName.isEmpty() || !aValidator.validate( aName, aPos ) )
159     return false;
160   return true;
161 }
162
163 //============================================================================
164 /*! Function : CheckValue
165  *  Purpose  : Return true if variable value correct, otherwise return false
166  */
167 //============================================================================
168 bool NoteBook_TableRow::CheckValue()
169 {
170   bool aResult = false;
171   QString aValue = GetValue();
172   if(!aValue.isEmpty() && 
173      (IsRealValue(aValue) ||
174       IsIntegerValue(aValue) ||
175       IsBooleanValue(aValue) ||
176       IsValidStringValue(aValue)))
177     aResult = true;
178   
179   return aResult;
180 }
181
182 //============================================================================
183 /*! Function : GetVariableItem
184  *  Purpose  : 
185  */
186 //============================================================================
187 QTableWidgetItem* NoteBook_TableRow::GetVariableItem()
188 {
189   return myVariableValue;
190 }
191
192 //============================================================================
193 /*! Function : GetNameItem
194  *  Purpose  : 
195  */
196 //============================================================================
197 QTableWidgetItem* NoteBook_TableRow::GetNameItem()
198 {
199   return myVariableName;
200 }
201
202 //============================================================================
203 /*! Function : GetHeaderItem
204  *  Purpose  : 
205  */
206 //============================================================================
207 QTableWidgetItem* NoteBook_TableRow::GetHeaderItem()
208 {
209   return myRowHeader;
210 }
211
212 //============================================================================
213 /*! Function : IsRealValue
214  *  Purpose  : Return true if theValue string is real value, otherwise return 
215  *             false
216  */
217 //============================================================================
218 bool NoteBook_TableRow::IsRealValue(const QString theValue, double* theResult)
219 {
220   bool aResult = false;
221   double aDResult = theValue.toDouble(&aResult);
222   if(aResult && theResult)
223     *theResult = aDResult;
224   
225   return aResult;
226 }
227
228 //============================================================================
229 /*! Function : IsBooleanValue
230  *  Purpose  : Return true if theValue String is boolean value, otherwise return 
231  *             false
232  */
233 //============================================================================
234 bool NoteBook_TableRow::IsBooleanValue(const QString theValue, bool* theResult){
235   bool aResult = false;
236   bool aBResult; 
237   if(theValue.compare("True") == 0) {
238     aBResult = true;
239     aResult = true;
240   }
241   else if(theValue.compare("False") == 0) {
242     aBResult = false;
243     aResult = true;
244   }
245   if(aResult && theResult)
246     *theResult = aBResult;
247   
248   return aResult;
249 }
250
251 //============================================================================
252 /*! Function : IsIntegerValue
253  *  Purpose  : Return true if theValue string is integer value, otherwise return 
254  *             false
255  */
256 //============================================================================
257 bool NoteBook_TableRow::IsIntegerValue(const QString theValue, int* theResult)
258 {
259   bool aResult = false;
260   int anIResult;
261   anIResult = theValue.toInt(&aResult);
262
263   if(aResult && theResult)
264     *theResult = anIResult;  
265   
266   return aResult;
267 }
268
269 //============================================================================
270 /*! Function : IsValidStringValue
271  *  Purpose  : Return true if theValue string is valid, otherwise return 
272  *             false
273  *             The string are always valid for the moment
274  *             The whole notebook is verified on apply
275  */
276 //============================================================================
277 bool NoteBook_TableRow::IsValidStringValue(const QString theValue)
278 {
279   int aNumRows = myParentTable->myRows.count();
280   if( aNumRows == 0 )
281     return true;
282
283   bool aLastRowIsEmpty = myParentTable->myRows[ aNumRows - 1 ]->GetName().isEmpty() &&
284                          myParentTable->myRows[ aNumRows - 1 ]->GetValue().isEmpty();
285
286   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
287   SalomePyConsole_Console* pyConsole = app->pythonConsole();
288   PyConsole_Interp* pyInterp = app->getPyInterp();
289   PyLockWrapper aLock; // Acquire GIL
290   std::string command = "import salome_notebook ; ";
291   command += "salome_notebook.checkThisNoteBook(";
292   for( int i = 0, n = aLastRowIsEmpty ? aNumRows - 1 : aNumRows; i < n; i++ ) {
293     command += myParentTable->myRows[i]->GetName().toStdString();
294     command += "=\"";
295     command += myParentTable->myRows[i]->GetValue().toStdString();
296     command += "\", ";
297   }
298   command += ") ";
299
300   //rnv: fix for bug 21947 WinTC5.1.4: Wrong error management of "Salome NoteBook"
301   bool oldSuppressValue = pyConsole->isSuppressOutput();
302   pyConsole->setIsSuppressOutput(true); 
303   bool aResult = pyInterp->run(command.c_str());
304   pyConsole->setIsSuppressOutput(oldSuppressValue);     
305   return !aResult;
306 }
307
308 ///////////////////////////////////////////////////////////////////////////
309 //                      NoteBook_Table class                             //
310 ///////////////////////////////////////////////////////////////////////////
311 //============================================================================
312 /*! Function : NoteBook_Table
313  *  Purpose  : Constructor
314  */
315 //============================================================================
316 NoteBook_Table::NoteBook_Table(QWidget * parent)
317   :QTableWidget(parent),
318    isProcessItemChangedSignal(false),
319    myIsModified(false)
320 {
321   setColumnCount(2);
322   setSelectionMode(QAbstractItemView::SingleSelection);
323   
324   //Add Headers Columns
325   QFont aFont = QFont();
326   aFont.setPointSize(10);
327   
328   //"Name" column
329   QTableWidgetItem * aNameHeader = new QTableWidgetItem();
330   aNameHeader->setText(tr("VARNAME_COLUMN"));
331   aNameHeader->setFont(aFont);
332   setHorizontalHeaderItem(0,aNameHeader);
333   setColumnWidth ( 0, COLUMN_SIZE);
334
335   //"Value" Column
336   QTableWidgetItem * aValueHeader = new QTableWidgetItem();
337   aValueHeader->setText(tr("VARVALUE_COLUMN"));
338   aValueHeader->setFont(aFont);
339   setHorizontalHeaderItem(1,aValueHeader);
340   setColumnWidth ( 1, COLUMN_SIZE);
341   setSortingEnabled(false);
342   
343   connect(this,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(onItemChanged(QTableWidgetItem*)));
344 }
345
346 //============================================================================
347 /*! Function : ~NoteBook_Table
348  *  Purpose  : Destructor
349  */
350 //============================================================================
351 NoteBook_Table::~NoteBook_Table(){}
352
353 //============================================================================
354 /*! Function : getUniqueIndex
355  *  Purpose  : Get a unique index for the new row
356  */
357 //============================================================================
358 int NoteBook_Table::getUniqueIndex() const
359 {
360   int anIndex = 0;
361   if( !myRows.isEmpty() )
362     if( NoteBook_TableRow* aRow = myRows.last() )
363       anIndex = aRow->GetIndex();
364
365   int aMaxRemovedRow = 0;
366   for( QListIterator<int> anIter( myRemovedRows ); anIter.hasNext(); )
367   {
368     int aRemovedRow = anIter.next();
369     aMaxRemovedRow = qMax( aRemovedRow, aMaxRemovedRow );
370   }
371
372   anIndex = qMax( anIndex, aMaxRemovedRow ) + 1;
373   return anIndex;
374 }
375
376 //============================================================================
377 /*! Function : Init
378  *  Purpose  : Add variables in the table from theStudy
379  */
380 //============================================================================
381 void NoteBook_Table::Init(_PTR(Study) theStudy)
382 {
383   isProcessItemChangedSignal = false;
384
385   int aNumRows = myRows.count();
386   if( aNumRows > 0 )
387   {
388     for( int i = 0; i < myRows.size(); i++ )
389     {
390       NoteBook_TableRow* aRow = myRows[ i ];
391       if( aRow )
392       {
393         delete aRow;
394         aRow = 0;
395       }
396     }
397     myRows.clear();
398   }
399   setRowCount( 0 );
400
401   myRemovedRows.clear();
402   myVariableMapRef.clear();
403   myVariableMap.clear();
404
405   //Add all variables into the table
406   std::vector<std::string> aVariables = theStudy->GetVariableNames();
407   for(int iVar = 0; iVar < aVariables.size(); iVar++ ) {
408     AddRow(QString(aVariables[iVar].c_str()),
409            Variable2String(aVariables[iVar],theStudy));
410   }
411
412   //Add empty row
413   AddEmptyRow();
414   isProcessItemChangedSignal = true;
415
416   ResetMaps();
417
418   myStudy = theStudy;
419 }
420
421 //============================================================================
422 /*! Function : Variable2String
423  *  Purpose  : Convert variable values to QString
424  */
425 //============================================================================
426 QString NoteBook_Table::Variable2String(const std::string& theVarName,
427                                         _PTR(Study) theStudy)
428 {
429   QString aResult;
430   if( theStudy->IsReal(theVarName) )
431     aResult = QString::number(theStudy->GetReal(theVarName));
432   else if( theStudy->IsInteger(theVarName) )
433     aResult = QString::number(theStudy->GetInteger(theVarName));
434   else if( theStudy->IsBoolean(theVarName) )
435     aResult = theStudy->GetBoolean(theVarName) ? QString("True") : QString("False");
436   else if( theStudy->IsString(theVarName) )
437     aResult = theStudy->GetString(theVarName).c_str();
438   
439   return aResult;
440 }
441
442 //============================================================================
443 /*! Function : IsValid
444  *  Purpose  : Check validity of the table data
445  */
446 //============================================================================
447 bool NoteBook_Table::IsValid() const
448 {
449   int aNumRows = myRows.count();
450   if( aNumRows == 0 )
451     return true;
452
453   bool aLastRowIsEmpty = myRows[ aNumRows - 1 ]->GetName().isEmpty() &&
454                          myRows[ aNumRows - 1 ]->GetValue().isEmpty();
455
456   for( int i = 0, n = aLastRowIsEmpty ? aNumRows - 1 : aNumRows; i < n; i++ )
457     if( !myRows[i]->CheckName() || !IsUniqueName( myRows[i] ) || !myRows[i]->CheckValue() )
458       return false;
459
460   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
461   SalomePyConsole_Console* pyConsole = app->pythonConsole();
462   PyConsole_Interp* pyInterp = app->getPyInterp();
463   PyLockWrapper aLock; // Acquire GIL
464   std::string command = "import salome_notebook ; ";
465   command += "salome_notebook.checkThisNoteBook(";
466   for( int i = 0, n = aLastRowIsEmpty ? aNumRows - 1 : aNumRows; i < n; i++ )
467     {
468       command += myRows[i]->GetName().toStdString();
469       command += "=\"";
470       command += myRows[i]->GetValue().toStdString();
471       command += "\",";
472     }
473   command += ")";
474
475   //rnv: fix for bug 21947 WinTC5.1.4: Wrong error management of "Salome NoteBook"
476   bool oldSuppressValue = pyConsole->isSuppressOutput();
477   pyConsole->setIsSuppressOutput(true); 
478   bool aResult = pyInterp->run(command.c_str());
479   pyConsole->setIsSuppressOutput(oldSuppressValue);     
480
481   return !aResult;
482 }
483
484 //============================================================================
485 /*! Function : RenumberRowItems
486  *  Purpose  : renumber row items
487  */
488 //============================================================================
489 void NoteBook_Table::RenumberRowItems() {
490   for(int i=0; i<myRows.size();i++){
491     myRows[i]->GetHeaderItem()->setText(QString::number(i+1));
492   }
493 }
494
495 //============================================================================
496 /*! Function : AddRow
497  *  Purpose  : Add a row into the table
498  */
499 //============================================================================
500 void NoteBook_Table::AddRow(const QString& theName, const QString& theValue)
501 {
502   int anIndex = getUniqueIndex();
503   NoteBook_TableRow* aRow = new NoteBook_TableRow(anIndex, this, this);
504   aRow->SetName(theName);
505   aRow->SetValue(theValue);
506   aRow->AddToTable(this);
507   myRows.append(aRow);
508
509   myVariableMap.insert( anIndex, NoteBoox_Variable( theName, theValue ) );
510 }
511
512 //============================================================================
513 /*! Function : AddEmptyRow
514  *  Purpose  : Add an empty row into the end of the table
515  */
516 //============================================================================
517 void NoteBook_Table::AddEmptyRow()
518 {
519   isProcessItemChangedSignal = false;
520   AddRow();
521   isProcessItemChangedSignal = true;
522 }
523
524 //============================================================================
525 /*! Function : GetRowByItem
526  *  Purpose  : 
527  */
528 //============================================================================
529 NoteBook_TableRow* NoteBook_Table::GetRowByItem(const QTableWidgetItem* theItem) const
530 {
531   int aCurrentRow = row(theItem);
532   
533   if( (myRows.size() <= aCurrentRow ) && (aCurrentRow < 0))
534     return NULL;
535   else
536     return myRows.at(aCurrentRow);
537 }
538
539 //============================================================================
540 /*! Function : IsLastRow
541  *  Purpose  : Return true if theRow is last row in the table
542  */
543 //============================================================================
544 bool NoteBook_Table::IsLastRow(const NoteBook_TableRow* theRow) const
545 {
546   return (myRows.last() == theRow);
547 }
548
549 //============================================================================
550 /*! Function : onItemChanged
551  *  Purpose  : [slot] called when table item changed
552  */
553 //============================================================================
554 void NoteBook_Table::onItemChanged(QTableWidgetItem* theItem)
555 {
556   if(isProcessItemChangedSignal) {
557     bool isModified = true;
558     NoteBook_TableRow* aRow = GetRowByItem(theItem);
559     if(aRow) {
560       int aCurrentColumn = column(theItem);
561       bool IsCorrect = true, IsVariableComplited = false;
562       QString aMsg;
563
564       if(aCurrentColumn == NAME_COLUMN) {
565         int anIndex = aRow->GetIndex();
566         if( myVariableMap.contains( anIndex ) )
567         {
568           const NoteBoox_Variable& aVariable = myVariableMap[ anIndex ];
569           if( !aVariable.Name.isEmpty() && myStudy->IsVariableUsed( std::string( aVariable.Name.toLatin1().constData() ) ) )
570           {
571             if( QMessageBox::warning( parentWidget(), tr( "WARNING" ),
572                                       tr( "RENAME_VARIABLE_IS_USED" ).arg( aVariable.Name ),
573                                       QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
574             {
575               bool isBlocked = blockSignals( true );
576               aRow->SetName( aVariable.Name );
577               blockSignals( isBlocked );
578               return;
579             }
580           }
581         }
582       }
583
584       //Case when variable name was changed.
585       if(aCurrentColumn == NAME_COLUMN) {
586         if(!aRow->CheckName()) {
587           IsCorrect = false;
588           aMsg = tr( "VARNAME_INCORRECT" ).arg(aRow->GetName());
589         }
590         else if(!IsUniqueName(aRow)) {
591           IsCorrect = false;
592           aMsg = tr( "VARNAME_EXISTS" ).arg(aRow->GetName());
593         }
594         else
595           IsVariableComplited = aRow->CheckValue();
596       }
597       
598       //Case when variable value was changed. 
599       else if(aCurrentColumn == VALUE_COLUMN){
600         if(!aRow->CheckValue()) {
601           IsCorrect = false;
602           aMsg = tr( "VARVALUE_INCORRECT" ).arg(aRow->GetName());
603         }
604         else
605           IsVariableComplited = aRow->CheckName() && IsUniqueName(aRow);
606       }
607
608       if(!IsCorrect && !aMsg.isEmpty())
609         SUIT_MessageBox::warning( parentWidget(), tr( "WARNING" ), aMsg );
610
611       bool isBlocked = blockSignals( true );
612       theItem->setForeground( QBrush( IsCorrect ? Qt::black : Qt::red ) );
613       blockSignals( isBlocked );
614
615       int anIndex = aRow->GetIndex();
616       if( myVariableMap.contains( anIndex ) )
617       {
618         NoteBoox_Variable& aVariable = myVariableMap[ anIndex ];
619         if( aVariable.Name.compare( aRow->GetName() ) != 0 ||
620             aVariable.Value.compare( aRow->GetValue() ) != 0 )
621         {
622           aVariable.Name = aRow->GetName();
623           aVariable.Value = aRow->GetValue();
624         }
625         else
626           isModified = false;
627       }
628
629       if(IsCorrect && IsVariableComplited && IsLastRow(aRow))
630         AddEmptyRow();
631
632       if( aRow->CheckName() && aRow->CheckValue() )
633         qobject_cast<SalomeApp_NoteBook*>(parentWidget())->onApply();
634     }
635
636     if( !myIsModified )
637       myIsModified = isModified;
638   }
639 }
640
641 //============================================================================
642 /*! Function : IsUniqueName
643  *  Purpose  : Return true if theName is unique name of the Variable
644  */
645 //============================================================================
646 bool NoteBook_Table::IsUniqueName(const NoteBook_TableRow* theRow) const
647 {
648   for(int i=0; i<myRows.size();i++) {
649     if(myRows[i] == theRow ) 
650       continue;
651     if(myRows[i]->GetName().compare(theRow->GetName()) == 0)
652       return false;
653   }
654   return true;
655 }
656
657 //============================================================================
658 /*! Function : RemoveSelected
659  *  Purpose  : Remove selected rows in the table
660  */
661 //============================================================================
662 void NoteBook_Table::RemoveSelected()
663 {
664   isProcessItemChangedSignal = false;
665   QList<QTableWidgetItem*> aSelectedItems = selectedItems();
666   if( !(aSelectedItems.size() > 0)) {
667     isProcessItemChangedSignal = true;
668     return;
669   }
670   bool removedFromStudy = false;
671   for(int i=0; i < aSelectedItems.size(); i++ ) {
672     NoteBook_TableRow* aRow = GetRowByItem(aSelectedItems[i]);
673     if(aRow) {
674       if(IsLastRow(aRow)) {
675         aRow->SetName(QString());
676         aRow->SetValue(QString());
677       }
678       else {
679         int nRow = row(aSelectedItems[i]);
680
681         if( myStudy->IsVariableUsed( std::string( aRow->GetName().toLatin1().constData() ) ) )
682         {
683           if( QMessageBox::warning( parentWidget(), tr( "WARNING" ),
684                                     tr( "REMOVE_VARIABLE_IS_USED" ).arg( aRow->GetName() ),
685                                     QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
686           {
687             isProcessItemChangedSignal = true;
688             return;
689           }
690         }
691
692         int index = aRow->GetIndex();
693         QString aVarName = aRow->GetName();
694         myRemovedRows.append( index );
695         if( myVariableMap.contains( index ) )
696           myVariableMap.remove( index );
697         removeRow(nRow);
698         myRows.removeAt(nRow);
699         if(myStudy->IsVariable(aVarName.toLatin1().constData()))
700           removedFromStudy = true;
701       }
702     }
703   }
704   if(removedFromStudy)
705     myIsModified = true;
706   RenumberRowItems();
707   isProcessItemChangedSignal = true;
708 }
709
710 //============================================================================
711 /*! Function : SetProcessItemChangedSignalFlag
712  *  Purpose  : 
713  */
714 //============================================================================
715 void NoteBook_Table::SetProcessItemChangedSignalFlag(const bool enable)
716 {
717   isProcessItemChangedSignal = enable;
718 }
719
720 //============================================================================
721 /*! Function : GetProcessItemChangedSignalFlag
722  *  Purpose  : 
723  */
724 //============================================================================
725 bool NoteBook_Table::GetProcessItemChangedSignalFlag() const
726 {
727   return isProcessItemChangedSignal;
728 }
729
730 //============================================================================
731 /*! Function : GetRows
732  *  Purpose  : 
733  */
734 //============================================================================
735 QList<NoteBook_TableRow*> NoteBook_Table::GetRows() const
736 {
737   return myRows;
738 }
739
740 //============================================================================
741 /*! Function : ResetMaps
742  *  Purpose  : Reset variable maps
743  */
744 //============================================================================
745 void NoteBook_Table::ResetMaps()
746 {
747   myIsModified = false;
748   myVariableMapRef = myVariableMap;
749   myRemovedRows.clear();
750 }
751
752 ///////////////////////////////////////////////////////////////////////////
753 //                  SalomeApp_NoteBook class                          //
754 ///////////////////////////////////////////////////////////////////////////
755 //============================================================================
756 /*! Function : SalomeApp_NoteBook
757  *  Purpose  : Constructor
758  */
759 //============================================================================
760 SalomeApp_NoteBook::SalomeApp_NoteBook(QWidget * parent, _PTR(Study) theStudy):
761   QWidget(parent),
762   myStudy(theStudy)
763 {
764   setObjectName("SalomeApp_NoteBook");
765   setWindowTitle(tr("NOTEBOOK_TITLE"));
766   QGridLayout* aLayout = new QGridLayout(this);
767
768   //Table
769   myTable = new NoteBook_Table(this);
770   aLayout->addWidget(myTable, 0, 0, 1, 3);
771   
772   //Buttons
773   myRemoveButton = new QPushButton(tr("BUT_REMOVE"));
774   aLayout->addWidget(myRemoveButton, 1, 0);
775
776   QSpacerItem* spacer =
777     new QSpacerItem(DEFAULT_SPACING, 5 , QSizePolicy::Expanding, QSizePolicy::Minimum);
778   aLayout->addItem(spacer, 1, 1);
779
780   myUpdateStudyBtn = new QPushButton(tr("BUT_UPDATE_STUDY"));
781   aLayout->addWidget(myUpdateStudyBtn, 1, 2);
782
783   QWidgetList aWidgetList;
784   aWidgetList.append( myTable );
785   aWidgetList.append( myUpdateStudyBtn );
786   aWidgetList.append( myRemoveButton );
787   Qtx::setTabOrder( aWidgetList );
788
789   connect( myUpdateStudyBtn, SIGNAL(clicked()), this, SLOT(onUpdateStudy()) );
790   connect( myRemoveButton, SIGNAL(clicked()), this, SLOT(onRemove()));
791   
792   myTable->Init(myStudy);
793
794   myDumpedStudyScript = "";  
795   myIsDumpedStudySaved = false;
796 }
797
798 //============================================================================
799 /*! Function : ~SalomeApp_NoteBook
800  *  Purpose  : Destructor
801  */
802 //============================================================================
803 SalomeApp_NoteBook::~SalomeApp_NoteBook(){}
804
805
806 //============================================================================
807 /*! Function : Init()
808  *  Purpose  : init variable table
809  */
810 //============================================================================
811 void SalomeApp_NoteBook::Init(_PTR(Study) theStudy){
812   if(myStudy!= theStudy)
813     myStudy = theStudy;
814   myTable->Init(myStudy);
815 }
816
817
818 //============================================================================
819 /*! Function : onVarUpdate
820  *  Purpose  : [slot]
821  */
822 //============================================================================
823 void SalomeApp_NoteBook::onVarUpdate(QString theVarName)
824 {
825   myTable->Init(myStudy);
826 }
827
828 //============================================================================
829 /*! Function : onApply
830  *  Purpose  : [slot]
831  */
832 //============================================================================
833 void SalomeApp_NoteBook::onApply()
834 {
835   if( !myTable->IsValid() )
836   {
837     SUIT_MessageBox::warning( this, tr( "WARNING" ), tr( "INCORRECT_DATA" ) );
838     return;
839   }
840
841   double aDVal;
842   int    anIVal;
843   bool   aBVal;
844
845   const QList<int>& aRemovedRows = myTable->GetRemovedRows();
846   const VariableMap& aVariableMap = myTable->GetVariableMap();
847   const VariableMap& aVariableMapRef = myTable->GetVariableMapRef();
848
849   for( QListIterator<int> anIter( aRemovedRows ); anIter.hasNext(); )
850   {
851     int anIndex = anIter.next();
852     if( aVariableMapRef.contains( anIndex ) )
853     {
854       QString aRemovedVariable = aVariableMapRef[ anIndex ].Name;
855       myStudy->RemoveVariable( std::string( aRemovedVariable.toLatin1().constData() ) );
856     }
857   }
858
859   VariableMap::const_iterator it = aVariableMap.constBegin(), itEnd = aVariableMap.constEnd();
860   for( ; it != itEnd; ++it )
861   {
862     int anIndex = it.key();
863     const NoteBoox_Variable& aVariable = it.value();
864     QString aName = aVariable.Name;
865     QString aValue = aVariable.Value;
866
867     if( !aName.isEmpty() && !aValue.isEmpty() )
868     {
869       if( aVariableMapRef.contains( anIndex ) )
870       {
871         const NoteBoox_Variable& aVariableRef = aVariableMapRef[ anIndex ];
872         QString aNameRef = aVariableRef.Name;
873         QString aValueRef = aVariableRef.Value;
874
875         if( !aNameRef.isEmpty() && !aValueRef.isEmpty() && aNameRef != aName )
876         {
877           myStudy->RenameVariable( std::string( aNameRef.toLatin1().constData() ),
878                                    std::string( aName.toLatin1().constData() ) );
879         }
880       }
881
882       if( NoteBook_TableRow::IsIntegerValue(aValue,&anIVal) )
883         myStudy->SetInteger(std::string(aName.toLatin1().constData()),anIVal);
884
885       else if( NoteBook_TableRow::IsRealValue(aValue,&aDVal) )
886         myStudy->SetReal(std::string(aName.toLatin1().constData()),aDVal);
887     
888       else if( NoteBook_TableRow::IsBooleanValue(aValue,&aBVal) )
889         myStudy->SetBoolean(std::string(aName.toLatin1().constData()),aBVal);
890     
891       else
892         myStudy->SetString(std::string(aName.toLatin1().constData()),aValue.toStdString());
893     }
894   }
895   myTable->ResetMaps();
896
897   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
898   if(app)
899     app->updateActions();
900   
901   myStudy->Modified();
902 }
903
904 //============================================================================
905 /*! Function : onRemove
906  *  Purpose  : [slot]
907  */
908 //============================================================================
909 void SalomeApp_NoteBook::onRemove()
910 {
911   myTable->RemoveSelected();
912   onApply();
913 }
914
915 //============================================================================
916 /*! Function : onUpdateStudy
917  *  Purpose  : [slot]
918  */
919 //============================================================================
920 void SalomeApp_NoteBook::onUpdateStudy()
921 {
922   onApply();
923   if( !myTable->IsValid() )
924     return;
925   
926   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
927   if(!app)
928     return;
929   app->onUpdateStudy();
930 }