]> SALOME platform Git repositories - modules/gui.git/blob - src/SalomeApp/SalomeApp_NoteBookDlg.cxx
Salome HOME
6005d889acdf28d65d248eaed48ebab4b0adf486
[modules/gui.git] / src / SalomeApp / SalomeApp_NoteBookDlg.cxx
1 // Copyright (C) 2008  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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.
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 // File:    SalomeApp_NoteBookDlg.cxx
20 // Author : Roman NIKOLAEV, Open CASCADE S.A.S.
21 // Module : GUI
22
23 #include "SalomeApp_NoteBookDlg.h"
24 #include "SalomeApp_Application.h"
25 #include "SalomeApp_Study.h"
26 #include "SalomeApp_VisualState.h"
27
28 #include <Qtx.h>
29
30 #include <CAM_Module.h>
31
32 #include <SUIT_Desktop.h>
33 #include <SUIT_MessageBox.h>
34 #include <SUIT_ResourceMgr.h>
35 #include <SUIT_Session.h>
36
37 #include <PyConsole_Console.h>
38
39 #include <SALOMEDS_Tool.hxx>
40
41 #include <QWidget>
42 #include <QDialog>
43 #include <QGridLayout>
44 #include <QTableWidget>
45 #include <QTableWidgetItem>
46 #include <QPushButton>
47 #include <QFont>
48 #include <QGroupBox>
49 #include <QList>
50 #include <QApplication>
51 #include <QDir>
52
53 #include <string>
54 #include <vector>
55
56 using namespace std;
57
58 #define DEFAULT_MARGIN  11
59 #define DEFAULT_SPACING 6
60 #define SPACER_SIZE     120
61 #define COLUMN_SIZE     180
62
63 #define NAME_COLUMN  0
64 #define VALUE_COLUMN 1
65
66
67 ///////////////////////////////////////////////////////////////////////////
68 //                 NoteBook_TableRow class                               //
69 ///////////////////////////////////////////////////////////////////////////
70 //============================================================================
71 /*! Function : NoteBook_TableRow
72  *  Purpose  : Constructor
73  */
74 //============================================================================
75 NoteBook_TableRow::NoteBook_TableRow(int index, QWidget* parent):
76   QWidget(parent),
77   myIndex(index),
78   myRowHeader(new QTableWidgetItem()),
79   myVariableName(new QTableWidgetItem()),
80   myVariableValue(new QTableWidgetItem())
81 {
82 }
83
84 //============================================================================
85 /*! Function : ~NoteBook_TableRow
86  *  Purpose  : Destructor
87  */
88 //============================================================================
89 NoteBook_TableRow::~NoteBook_TableRow()
90 {
91 }
92
93 //============================================================================
94 /*! Function : AddToTable
95  *  Purpose  : Add this row to the table theTable
96  */
97 //============================================================================
98 void NoteBook_TableRow::AddToTable(QTableWidget *theTable)
99 {
100   int aPosition = theTable->rowCount();
101   int aRowCount = aPosition+1;
102   theTable->setRowCount(aRowCount);
103   myRowHeader->setText(QString::number(aRowCount));
104
105   theTable->setVerticalHeaderItem(aPosition,myRowHeader);
106   theTable->setItem(aPosition, NAME_COLUMN, myVariableName);
107   theTable->setItem(aPosition, VALUE_COLUMN, myVariableValue);
108 }
109
110 //============================================================================
111 /*! Function : SetName
112  *  Purpose  : 
113  */
114 //============================================================================
115 void NoteBook_TableRow::SetName(const QString theName)
116 {
117   myVariableName->setText(theName);
118 }
119
120 //============================================================================
121 /*! Function : SetValue
122  *  Purpose  : 
123  */
124 //============================================================================
125 void NoteBook_TableRow::SetValue(const QString theValue)
126 {
127   myVariableValue->setText(theValue);
128 }
129
130 //============================================================================
131 /*! Function : GetName
132  *  Purpose  : Return variable name
133  */
134 //============================================================================
135 QString NoteBook_TableRow::GetName() const
136 {
137   return myVariableName->text();
138 }
139
140 //============================================================================
141 /*! Function : GetValue
142  *  Purpose  : Return variable value
143  */
144 //============================================================================
145 QString NoteBook_TableRow::GetValue() const
146 {
147   return myVariableValue->text(); 
148 }
149
150 //============================================================================
151 /*! Function : CheckName
152  *  Purpose  : Return true if variable name correct, otherwise return false
153  */
154 //============================================================================
155 bool NoteBook_TableRow::CheckName()
156 {
157   QString aName = GetName();
158   int aPos = 0;
159   QRegExpValidator aValidator( QRegExp("^([a-zA-Z]+)([a-zA-Z0-9_]*)$"), 0 );
160   if( aName.isEmpty() || !aValidator.validate( aName, aPos ) )
161     return false;
162   return true;
163 }
164
165 //============================================================================
166 /*! Function : CheckValue
167  *  Purpose  : Return true if variable value correct, otherwise return false
168  */
169 //============================================================================
170 bool NoteBook_TableRow::CheckValue()
171 {
172   bool aResult = false;
173   QString aValue = GetValue();
174   if( (!aValue.isEmpty()) && 
175       (IsRealValue(aValue)) ||
176       IsIntegerValue(aValue)||
177       IsBooleanValue(aValue)) 
178     aResult = true;
179   
180   return aResult;
181 }
182
183 //============================================================================
184 /*! Function : GetVariableItem
185  *  Purpose  : 
186  */
187 //============================================================================
188 QTableWidgetItem* NoteBook_TableRow::GetVariableItem()
189 {
190   return myVariableValue;
191 }
192
193 //============================================================================
194 /*! Function : GetNameItem
195  *  Purpose  : 
196  */
197 //============================================================================
198 QTableWidgetItem* NoteBook_TableRow::GetNameItem()
199 {
200   return myVariableName;
201 }
202
203 //============================================================================
204 /*! Function : GetHeaderItem
205  *  Purpose  : 
206  */
207 //============================================================================
208 QTableWidgetItem* NoteBook_TableRow::GetHeaderItem()
209 {
210   return myRowHeader;
211 }
212
213 //============================================================================
214 /*! Function : IsRealValue
215  *  Purpose  : Return true if theValue string is real value, otherwise return 
216  *             false
217  */
218 //============================================================================
219 bool NoteBook_TableRow::IsRealValue(const QString theValue, double* theResult)
220 {
221   bool aResult = false;
222   double aDResult = theValue.toDouble(&aResult);
223   if(theResult)
224     *theResult = aDResult;
225   
226   return aResult;
227 }
228
229 //============================================================================
230 /*! Function : IsBooleanValue
231  *  Purpose  : Return true if theValue String is boolean value, otherwise return 
232  *             false
233  */
234 //============================================================================
235 bool NoteBook_TableRow::IsBooleanValue(const QString theValue, bool* theResult){
236   bool aResult = false;
237   bool aBResult; 
238   if(theValue.compare("True") == 0) {
239     aBResult = true;
240     aResult = true;
241   }
242   else if(theValue.compare("False") == 0) {
243     aBResult = false;
244     aResult = true;
245   }
246   if(theResult)
247     *theResult = aBResult;
248   
249   return aResult;
250 }
251
252 //============================================================================
253 /*! Function : IsIntegerValue
254  *  Purpose  : Return true if theValue string is integer value, otherwise return 
255  *             false
256  */
257 //============================================================================
258 bool NoteBook_TableRow::IsIntegerValue(const QString theValue, int* theResult)
259 {
260   bool aResult = false;
261   int anIResult;
262   anIResult = theValue.toInt(&aResult);
263
264   if(theResult)
265     *theResult = anIResult;  
266   
267   return aResult;
268 }
269
270
271 ///////////////////////////////////////////////////////////////////////////
272 //                      NoteBook_Table class                             //
273 ///////////////////////////////////////////////////////////////////////////
274 //============================================================================
275 /*! Function : NoteBook_Table
276  *  Purpose  : Constructor
277  */
278 //============================================================================
279 NoteBook_Table::NoteBook_Table(QWidget * parent)
280   :QTableWidget(parent),
281    isProcessItemChangedSignal(false),
282    myIsModified(false)
283 {
284   setColumnCount(2);
285   setSelectionMode(QAbstractItemView::SingleSelection);
286   
287   //Add Headers Columns
288   QFont aFont = QFont();
289   aFont.setBold(true);
290   aFont.setPointSize(10);
291   
292   //"Name" column
293   QTableWidgetItem * aNameHeader = new QTableWidgetItem();
294   aNameHeader->setText(tr("VARNAME_COLUMN"));
295   aNameHeader->setFont(aFont);
296   setHorizontalHeaderItem(0,aNameHeader);
297   setColumnWidth ( 0, COLUMN_SIZE);
298
299   //"Value" Column
300   QTableWidgetItem * aValueHeader = new QTableWidgetItem();
301   aValueHeader->setText(tr("VARVALUE_COLUMN"));
302   aValueHeader->setFont(aFont);
303   setHorizontalHeaderItem(1,aValueHeader);
304   setColumnWidth ( 1, COLUMN_SIZE);
305   setSortingEnabled(false);
306   
307   connect(this,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(onItemChanged(QTableWidgetItem*)));
308 }
309
310 //============================================================================
311 /*! Function : ~NoteBook_Table
312  *  Purpose  : Destructor
313  */
314 //============================================================================
315 NoteBook_Table::~NoteBook_Table(){}
316
317 //============================================================================
318 /*! Function : getUniqueIndex
319  *  Purpose  : Get a unique index for the new row
320  */
321 //============================================================================
322 int NoteBook_Table::getUniqueIndex() const
323 {
324   int anIndex = 0;
325   if( !myRows.isEmpty() )
326     if( NoteBook_TableRow* aRow = myRows.last() )
327       anIndex = aRow->GetIndex();
328
329   int aMaxRemovedRow = 0;
330   for( QListIterator<int> anIter( myRemovedRows ); anIter.hasNext(); )
331   {
332     int aRemovedRow = anIter.next();
333     aMaxRemovedRow = qMax( aRemovedRow, aMaxRemovedRow );
334   }
335
336   anIndex = qMax( anIndex, aMaxRemovedRow ) + 1;
337   return anIndex;
338 }
339
340 //============================================================================
341 /*! Function : Init
342  *  Purpose  : Add variables in the table from theStudy
343  */
344 //============================================================================
345 void NoteBook_Table::Init(_PTR(Study) theStudy)
346 {
347   isProcessItemChangedSignal = false;
348
349   int aNumRows = myRows.count();
350   if( aNumRows > 0 )
351   {
352     for( int i = 0; i < myRows.size(); i++ )
353     {
354       NoteBook_TableRow* aRow = myRows[ i ];
355       if( aRow )
356       {
357         delete aRow;
358         aRow = 0;
359       }
360     }
361     myRows.clear();
362   }
363   setRowCount( 0 );
364
365   myRemovedRows.clear();
366   myVariableMapRef.clear();
367   myVariableMap.clear();
368
369   //Add all variables into the table
370   vector<string> aVariables = theStudy->GetVariableNames();
371   for(int iVar = 0; iVar < aVariables.size(); iVar++ ) {
372     AddRow(QString(aVariables[iVar].c_str()),
373            Variable2String(aVariables[iVar],theStudy));
374   }
375
376   //Add empty row
377   AddEmptyRow();
378   isProcessItemChangedSignal = true;
379
380   ResetMaps();
381
382   myStudy = theStudy;
383 }
384
385 //============================================================================
386 /*! Function : Variable2String
387  *  Purpose  : Convert variable values to QString
388  */
389 //============================================================================
390 QString NoteBook_Table::Variable2String(const string& theVarName,
391                                         _PTR(Study) theStudy)
392 {
393   QString aResult;
394   if( theStudy->IsReal(theVarName) )
395     aResult = QString::number(theStudy->GetReal(theVarName));
396   else if( theStudy->IsInteger(theVarName) )
397     aResult = QString::number(theStudy->GetInteger(theVarName));
398   else if( theStudy->IsBoolean(theVarName) )
399     aResult = theStudy->GetBoolean(theVarName) ? QString("True") : QString("False");
400   
401   return aResult;
402 }
403
404 //============================================================================
405 /*! Function : IsValid
406  *  Purpose  : Check validity of the table data
407  */
408 //============================================================================
409 bool NoteBook_Table::IsValid() const
410 {
411   int aNumRows = myRows.count();
412   if( aNumRows == 0 )
413     return true;
414
415   bool aLastRowIsEmpty = myRows[ aNumRows - 1 ]->GetName().isEmpty() &&
416                          myRows[ aNumRows - 1 ]->GetValue().isEmpty();
417
418   for( int i = 0, n = aLastRowIsEmpty ? aNumRows - 1 : aNumRows; i < n; i++ )
419     if( !myRows[i]->CheckName() || !IsUniqueName( myRows[i] ) || !myRows[i]->CheckValue() )
420       return false;
421
422   return true;
423 }
424
425 //============================================================================
426 /*! Function : RenamberRowItems
427  *  Purpose  : renumber row items
428  */
429 //============================================================================
430 void NoteBook_Table::RenamberRowItems(){
431   for(int i=0; i<myRows.size();i++){
432     myRows[i]->GetHeaderItem()->setText(QString::number(i+1));
433   }
434 }
435
436 //============================================================================
437 /*! Function : AddRow
438  *  Purpose  : Add a row into the table
439  */
440 //============================================================================
441 void NoteBook_Table::AddRow(const QString& theName, const QString& theValue)
442 {
443   int anIndex = getUniqueIndex();
444   NoteBook_TableRow* aRow = new NoteBook_TableRow(anIndex, this);
445   aRow->SetName(theName);
446   aRow->SetValue(theValue);
447   aRow->AddToTable(this);
448   myRows.append(aRow);
449
450   myVariableMap.insert( anIndex, NoteBoox_Variable( theName, theValue ) );
451 }
452
453 //============================================================================
454 /*! Function : AddEmptyRow
455  *  Purpose  : Add an empty row into the end of the table
456  */
457 //============================================================================
458 void NoteBook_Table::AddEmptyRow()
459 {
460   isProcessItemChangedSignal = false;
461   AddRow();
462   isProcessItemChangedSignal = true;
463 }
464
465 //============================================================================
466 /*! Function : GetRowByItem
467  *  Purpose  : 
468  */
469 //============================================================================
470 NoteBook_TableRow* NoteBook_Table::GetRowByItem(const QTableWidgetItem* theItem) const
471 {
472   int aCurrentRow = row(theItem);
473   
474   if( (myRows.size() <= aCurrentRow ) && (aCurrentRow < 0))
475     return NULL;
476   else
477     return myRows.at(aCurrentRow);
478 }
479
480 //============================================================================
481 /*! Function : IsLastRow
482  *  Purpose  : Return true if theRow is last row in the table
483  */
484 //============================================================================
485 bool NoteBook_Table::IsLastRow(const NoteBook_TableRow* theRow) const
486 {
487   return (myRows.last() == theRow);
488 }
489
490 //============================================================================
491 /*! Function : onItemChanged
492  *  Purpose  : [slot] called then table item changed
493  */
494 //============================================================================
495 void NoteBook_Table::onItemChanged(QTableWidgetItem* theItem)
496 {
497   if(isProcessItemChangedSignal) {
498     bool isModified = true;
499     NoteBook_TableRow* aRow = GetRowByItem(theItem);
500     if(aRow) {
501       int aCurrentColumn = column(theItem);
502       bool IsCorrect = true, IsVariableComplited = false;
503       QString aMsg;
504
505       if(aCurrentColumn == NAME_COLUMN) {
506         int anIndex = aRow->GetIndex();
507         if( myVariableMap.contains( anIndex ) )
508         {
509           const NoteBoox_Variable& aVariable = myVariableMap[ anIndex ];
510           if( !aVariable.Name.isEmpty() && myStudy->IsVariableUsed( string( aVariable.Name.toLatin1().constData() ) ) )
511           {
512             if( QMessageBox::warning( parentWidget(), tr( "WARNING" ),
513                                       tr( "RENAME_VARIABLE_IS_USED" ).arg( aVariable.Name ),
514                                       QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
515             {
516               bool isBlocked = blockSignals( true );
517               aRow->SetName( aVariable.Name );
518               blockSignals( isBlocked );
519               return;
520             }
521           }
522         }
523       }
524
525       //Case then varible name changed. 
526       if(aCurrentColumn == NAME_COLUMN) {
527         if(!aRow->CheckName()) {
528           IsCorrect = false;
529           aMsg = tr( "VARNAME_INCORRECT" ).arg(aRow->GetName());
530         }
531         else if(!IsUniqueName(aRow)) {
532           IsCorrect = false;
533           aMsg = tr( "VARNAME_EXISTS" ).arg(aRow->GetName());
534         }
535         else
536           IsVariableComplited = aRow->CheckValue();
537       }
538       
539       //Case then varible value changed. 
540       else if(aCurrentColumn == VALUE_COLUMN){
541         if(!aRow->CheckValue()) {
542           IsCorrect = false;
543           aMsg = tr( "VARVALUE_INCORRECT" ).arg(aRow->GetName());
544         }
545         else
546           IsVariableComplited = aRow->CheckName() && IsUniqueName(aRow);
547       }
548
549       if(!IsCorrect && !aMsg.isEmpty())
550         SUIT_MessageBox::warning( parentWidget(), tr( "WARNING" ), aMsg );
551
552       bool isBlocked = blockSignals( true );
553       theItem->setForeground( QBrush( IsCorrect ? Qt::black : Qt::red ) );
554       blockSignals( isBlocked );
555
556       int anIndex = aRow->GetIndex();
557       if( myVariableMap.contains( anIndex ) )
558       {
559         NoteBoox_Variable& aVariable = myVariableMap[ anIndex ];
560         if( aVariable.Name.compare( aRow->GetName() ) != 0 ||
561             aVariable.Value.compare( aRow->GetValue() ) != 0 )
562         {
563           aVariable.Name = aRow->GetName();
564           aVariable.Value = aRow->GetValue();
565         }
566         else
567           isModified = false;
568       }
569
570       if(IsCorrect && IsVariableComplited && IsLastRow(aRow))
571         AddEmptyRow();
572     }
573
574     if( !myIsModified )
575       myIsModified = isModified;
576   }
577 }
578
579 //============================================================================
580 /*! Function : IsUniqueName
581  *  Purpose  : Return true if theName is unique name of the Variable
582  */
583 //============================================================================
584 bool NoteBook_Table::IsUniqueName(const NoteBook_TableRow* theRow) const
585 {
586   for(int i=0; i<myRows.size();i++) {
587     if(myRows[i] == theRow ) 
588       continue;
589     if(myRows[i]->GetName().compare(theRow->GetName()) == 0)
590       return false;
591   }
592   return true;
593 }
594
595 //============================================================================
596 /*! Function : RemoveSelected
597  *  Purpose  : Remove selected rows in the table
598  */
599 //============================================================================
600 void NoteBook_Table::RemoveSelected()
601 {
602   isProcessItemChangedSignal = false;
603   QList<QTableWidgetItem*> aSelectedItems = selectedItems();
604   if( !(aSelectedItems.size() > 0)) {
605     isProcessItemChangedSignal = true;
606     return;
607   }
608   bool removedFromStudy = false;
609   for(int i=0; i < aSelectedItems.size(); i++ ) {
610     NoteBook_TableRow* aRow = GetRowByItem(aSelectedItems[i]);
611     if(aRow) {
612       if(IsLastRow(aRow)) {
613         aRow->SetName(QString());
614         aRow->SetValue(QString());
615       }
616       else {
617         int nRow = row(aSelectedItems[i]);
618
619         if( myStudy->IsVariableUsed( string( aRow->GetName().toLatin1().constData() ) ) )
620         {
621           if( QMessageBox::warning( parentWidget(), tr( "WARNING" ),
622                                     tr( "REMOVE_VARIABLE_IS_USED" ).arg( aRow->GetName() ),
623                                     QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
624           {
625             isProcessItemChangedSignal = true;
626             return;
627           }
628         }
629
630         int index = aRow->GetIndex();
631         QString aVarName = aRow->GetName();
632         myRemovedRows.append( index );
633         if( myVariableMap.contains( index ) )
634           myVariableMap.remove( index );
635         removeRow(nRow);
636         myRows.removeAt(nRow);
637         if(myStudy->IsVariable(aVarName.toLatin1().constData()))
638           removedFromStudy = true;
639       }
640     }
641   }
642   if(removedFromStudy)
643     myIsModified = true;
644   RenamberRowItems();
645   isProcessItemChangedSignal = true;
646 }
647
648 //============================================================================
649 /*! Function : SetProcessItemChangedSignalFlag
650  *  Purpose  : 
651  */
652 //============================================================================
653 void NoteBook_Table::SetProcessItemChangedSignalFlag(const bool enable)
654 {
655   isProcessItemChangedSignal = enable;
656 }
657
658 //============================================================================
659 /*! Function : GetProcessItemChangedSignalFlag
660  *  Purpose  : 
661  */
662 //============================================================================
663 bool NoteBook_Table::GetProcessItemChangedSignalFlag() const
664 {
665   return isProcessItemChangedSignal;
666 }
667
668 //============================================================================
669 /*! Function : GetRows
670  *  Purpose  : 
671  */
672 //============================================================================
673 QList<NoteBook_TableRow*> NoteBook_Table::GetRows() const
674 {
675   return myRows;
676 }
677
678 //============================================================================
679 /*! Function : ResetMaps
680  *  Purpose  : Reset variable maps
681  */
682 //============================================================================
683 void NoteBook_Table::ResetMaps()
684 {
685   myIsModified = false;
686   myVariableMapRef = myVariableMap;
687   myRemovedRows.clear();
688 }
689
690 ///////////////////////////////////////////////////////////////////////////
691 //                  SalomeApp_NoteBookDlg class                          //
692 ///////////////////////////////////////////////////////////////////////////
693 //============================================================================
694 /*! Function : SalomeApp_NoteBookDlg
695  *  Purpose  : Constructor
696  */
697 //============================================================================
698 SalomeApp_NoteBookDlg::SalomeApp_NoteBookDlg(QWidget * parent, _PTR(Study) theStudy):
699   QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
700   myStudy(theStudy)
701 {
702   setModal(false);
703   setObjectName("SalomeApp_NoteBookDlg");
704   setWindowTitle(tr("NOTEBOOK_TITLE"));
705   QGridLayout* aLayout = new QGridLayout(this);
706   aLayout->setMargin(DEFAULT_MARGIN);
707   aLayout->setSpacing(DEFAULT_SPACING);
708
709   //Table
710   myTable = new NoteBook_Table(this);
711   aLayout->addWidget(myTable, 0, 0, 1, 3);
712   
713   //Buttons
714   myRemoveButton = new QPushButton(tr("BUT_REMOVE"));
715   aLayout->addWidget(myRemoveButton, 1, 0, 1, 1);
716
717   QSpacerItem* spacer =
718     new QSpacerItem(DEFAULT_SPACING, 5 , QSizePolicy::Expanding, QSizePolicy::Minimum);
719   aLayout->addItem(spacer, 1, 1, 2, 1);
720
721   myUpdateStudyBtn = new QPushButton(tr("BUT_UPDATE_STUDY"));
722   aLayout->addWidget(myUpdateStudyBtn, 1, 2, 1, 1);
723   
724   QGroupBox* groupBox = new QGroupBox(this);
725
726   QGridLayout* aLayout1 = new QGridLayout(groupBox);
727
728   aLayout1->setMargin(DEFAULT_MARGIN);
729   aLayout1->setSpacing(DEFAULT_SPACING);
730
731   myOkBtn = new QPushButton(tr("BUT_APPLY_AND_CLOSE"));
732   aLayout1->addWidget(myOkBtn, 0, 0, 1, 1);
733   
734   myApplyBtn = new QPushButton(tr("BUT_APPLY"));
735   aLayout1->addWidget(myApplyBtn, 0, 1, 1, 1);  
736
737   QSpacerItem* spacer1 =
738     new QSpacerItem(DEFAULT_SPACING, 5, QSizePolicy::Expanding, QSizePolicy::Minimum);
739   aLayout1->addItem(spacer1, 0, 2, 1, 1);
740
741   myCancelBtn = new QPushButton(tr("BUT_CLOSE"));
742   aLayout1->addWidget(myCancelBtn, 0, 3, 1, 1);
743
744   myHelpBtn = new QPushButton(tr("BUT_HELP"));
745   aLayout1->addWidget(myHelpBtn, 0, 4, 1, 1);
746   
747   aLayout->addWidget(groupBox, 2, 0, 1, 3);
748
749   QWidgetList aWidgetList;
750   aWidgetList.append( myTable );
751   aWidgetList.append( myOkBtn );
752   aWidgetList.append( myApplyBtn );
753   aWidgetList.append( myCancelBtn );
754   aWidgetList.append( myHelpBtn );
755   aWidgetList.append( myUpdateStudyBtn );
756   aWidgetList.append( myRemoveButton );
757   Qtx::setTabOrder( aWidgetList );
758
759   connect( myOkBtn, SIGNAL(clicked()), this, SLOT(onOK()) );
760   connect( myApplyBtn, SIGNAL(clicked()), this, SLOT(onApply()) );
761   connect( myCancelBtn, SIGNAL(clicked()), this, SLOT(onCancel()) );
762   connect( myUpdateStudyBtn, SIGNAL(clicked()), this, SLOT(onUpdateStudy()) );
763   connect( myRemoveButton, SIGNAL(clicked()), this, SLOT(onRemove()));
764   connect( myHelpBtn, SIGNAL(clicked()), this, SLOT(onHelp()));
765   
766   myTable->Init(myStudy);
767 }
768
769 //============================================================================
770 /*! Function : ~SalomeApp_NoteBookDlg
771  *  Purpose  : Destructor
772  */
773 //============================================================================
774 SalomeApp_NoteBookDlg::~SalomeApp_NoteBookDlg(){}
775
776
777 //============================================================================
778 /*! Function : Init()
779  *  Purpose  : init variable table
780  */
781 //============================================================================
782 void SalomeApp_NoteBookDlg::Init(_PTR(Study) theStudy){
783   if(myStudy!= theStudy)
784     myStudy = theStudy;
785   myTable->Init(myStudy);
786 }
787
788
789 //============================================================================
790 /*! Function : onOK
791  *  Purpose  : [slot]
792  */
793 //============================================================================
794 void SalomeApp_NoteBookDlg::onOK()
795 {
796   onApply();
797   if( myTable->IsValid() )
798     accept();
799 }
800
801 //============================================================================
802 /*! Function : onHelp
803  *  Purpose  : [slot]
804  */
805 //============================================================================
806 void SalomeApp_NoteBookDlg::onHelp()
807 {
808   QString aHelpFileName("using_notebook.html");
809   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
810   if (app)
811     app->onHelpContextModule("GUI",aHelpFileName);
812   else {
813     QString platform;
814 #ifdef WIN32
815     platform = "winapplication";
816 #else
817     platform = "application";
818 #endif
819     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
820                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
821                              arg(app->resourceMgr()->stringValue("ExternalBrowser",
822                                                                  platform)).
823                              arg(aHelpFileName));
824   }
825
826 }
827 //============================================================================
828 /*! Function : onApply
829  *  Purpose  : [slot]
830  */
831 //============================================================================
832 void SalomeApp_NoteBookDlg::onApply()
833 {
834   if( !myTable->IsValid() )
835   {
836     SUIT_MessageBox::warning( this, tr( "WARNING" ), tr( "INCORRECT_DATA" ) );
837     return;
838   }
839
840   double aDVal;
841   int    anIVal;
842   bool   aBVal;
843
844   const QList<int>& aRemovedRows = myTable->GetRemovedRows();
845   const VariableMap& aVariableMap = myTable->GetVariableMap();
846   const VariableMap& aVariableMapRef = myTable->GetVariableMapRef();
847
848   for( QListIterator<int> anIter( aRemovedRows ); anIter.hasNext(); )
849   {
850     int anIndex = anIter.next();
851     if( aVariableMapRef.contains( anIndex ) )
852     {
853       QString aRemovedVariable = aVariableMapRef[ anIndex ].Name;
854       myStudy->RemoveVariable( string( aRemovedVariable.toLatin1().constData() ) );
855     }
856   }
857
858   VariableMap::const_iterator it = aVariableMap.constBegin(), itEnd = aVariableMap.constEnd();
859   for( ; it != itEnd; ++it )
860   {
861     int anIndex = it.key();
862     const NoteBoox_Variable& aVariable = it.value();
863     QString aName = aVariable.Name;
864     QString aValue = aVariable.Value;
865
866     if( !aName.isEmpty() && !aValue.isEmpty() )
867     {
868       if( aVariableMapRef.contains( anIndex ) )
869       {
870         const NoteBoox_Variable& aVariableRef = aVariableMapRef[ anIndex ];
871         QString aNameRef = aVariableRef.Name;
872         QString aValueRef = aVariableRef.Value;
873
874         if( !aNameRef.isEmpty() && !aValueRef.isEmpty() && aNameRef != aName )
875         {
876           myStudy->RenameVariable( string( aNameRef.toLatin1().constData() ),
877                                    string( aName.toLatin1().constData() ) );
878         }
879       }
880
881       if( NoteBook_TableRow::IsIntegerValue(aValue,&anIVal) )
882         myStudy->SetInteger(string(aName.toLatin1().constData()),anIVal);
883
884       else if( NoteBook_TableRow::IsRealValue(aValue,&aDVal) )
885         myStudy->SetReal(string(aName.toLatin1().constData()),aDVal);
886     
887       else if( NoteBook_TableRow::IsBooleanValue(aValue,&aBVal) )
888         myStudy->SetBoolean(string(aName.toLatin1().constData()),aBVal);
889     }
890   }
891   myTable->ResetMaps();
892
893   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
894   if(app)
895     app->updateActions();
896
897 }
898
899 //============================================================================
900 /*! Function : onCancel
901  *  Purpose  : [slot]
902  */
903 //============================================================================
904 void SalomeApp_NoteBookDlg::onCancel()
905 {
906   if( myTable->IsModified() )
907   {
908     int answer = QMessageBox::question( this, tr( "CLOSE_CAPTION" ), tr( "CLOSE_DESCRIPTION" ),
909                                         QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel );
910     switch( answer )
911     {
912       case QMessageBox::Yes    : onOK(); return;
913       case QMessageBox::No     : break;
914       case QMessageBox::Cancel : return;
915       default : break;
916     }
917   }
918   reject();
919 }
920
921 //============================================================================
922 /*! Function : onRemove
923  *  Purpose  : [slot]
924  */
925 //============================================================================
926 void SalomeApp_NoteBookDlg::onRemove()
927 {
928   myTable->RemoveSelected();
929 }
930
931 //============================================================================
932 /*! Function : onUpdateStudy
933  *  Purpose  : [slot]
934  */
935 //============================================================================
936 void SalomeApp_NoteBookDlg::onUpdateStudy()
937 {
938   onApply();
939   if( !myTable->IsValid() )
940     return;
941
942   QApplication::setOverrideCursor( Qt::WaitCursor );
943
944   if( !updateStudy() )
945     SUIT_MessageBox::warning( this, tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
946     
947   QApplication::restoreOverrideCursor();
948 }
949
950 //============================================================================
951 /*! Function : updateStudy
952  *  Purpose  : 
953  */
954 //============================================================================
955 bool SalomeApp_NoteBookDlg::updateStudy()
956 {
957   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
958   if( !app )
959     return false;
960
961   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( app->activeStudy() );
962   if( !study )
963     return false;
964
965   bool isStudySaved = study->isSaved();
966   QString aStudyName = study->studyName();
967
968   _PTR(Study) studyDS = study->studyDS();
969
970   // get unique temporary directory name
971   QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
972   if( aTmpDir.isEmpty() )
973     return false;
974
975   if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
976     aTmpDir.remove( aTmpDir.length() - 1, 1 );
977
978   // dump study to the temporary directory
979   QString aFileName( "notebook" );
980   bool toPublish = true;
981   bool toSaveGUI = true;
982
983   int savePoint;
984   _PTR(AttributeParameter) ap;
985   _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
986   if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
987   if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
988     ip->setDumpPython(studyDS);
989     savePoint = SalomeApp_VisualState( app ).storeState(); //SRN: create a temporary save point
990   }
991   bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aFileName.toStdString(), toPublish );
992   if ( toSaveGUI )
993     study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
994
995   if( !ok )
996     return false;
997
998   // clear a study (delete all objects)
999   clearStudy();
1000
1001   // get active application
1002   app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
1003
1004   // load study from the temporary directory
1005   QString command = QString( "execfile(\"%1\")" ).arg( aTmpDir + QDir::separator() + aFileName + ".py" );
1006
1007   PyConsole_Console* pyConsole = app->pythonConsole();
1008   if ( pyConsole )
1009     pyConsole->execAndWait( command );
1010
1011   // remove temporary directory
1012   QDir aDir( aTmpDir );
1013   QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
1014   for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
1015     ok = aDir.remove( *it ) && ok;
1016   if( ok )
1017     ok = aDir.rmdir( aTmpDir );
1018
1019   if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
1020   {
1021     myStudy = newStudy->studyDS();
1022     myTable->Init(myStudy);
1023     if(isStudySaved) {
1024       newStudy->markAsSavedIn(aStudyName);
1025     }
1026   }
1027   else
1028     ok = false;
1029
1030   return ok;
1031 }
1032
1033 //============================================================================
1034 /*! Function : clearStudy
1035  *  Purpose  : 
1036  */
1037 //============================================================================
1038 void SalomeApp_NoteBookDlg::clearStudy()
1039 {
1040   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
1041   if( !app )
1042     return;
1043
1044   QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1045   int anIndex = aList.indexOf( app );
1046
1047   //Store position and size of the this dialog
1048   int aW = width();
1049   int aH = height();
1050   int aX = x();
1051   int aY = y();
1052
1053   // Disconnect dialog from application desktop in case if:
1054   // 1) Application is not the first application in the session 
1055   // 2) Application is the first application in session but not the only.
1056   bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1057
1058   if( changeDesktop )
1059     setParent( 0 );
1060
1061   app->onCloseDoc( false );
1062   
1063   if( anIndex > 0 && anIndex < aList.count() )
1064     app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
1065   else if(anIndex == 0 && aList.count() > 1)
1066     app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
1067
1068   if( !app )
1069     return;
1070
1071   app->onNewDoc();
1072
1073   app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
1074   if( changeDesktop && app ) {
1075     setParent( app->desktop(), Qt::Dialog );
1076     app->setNoteBook(this);
1077   }
1078   //Set position and size of the this dialog
1079   resize( aW, aH );
1080   move( aX, aY );
1081   show();
1082 }