Salome HOME
Updated copyright comment
[modules/gui.git] / src / SalomeApp / SalomeApp_NoteBook.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, 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 "PyConsole_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   myIndex(index),
75   myParentTable(parentTable),
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   PyConsole_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()
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 = SalomeApp_Application::getStudy()->GetVariableNames();
407   for(int iVar = 0; iVar < (int)aVariables.size(); iVar++ ) {
408     AddRow(QString(aVariables[iVar].c_str()),
409            Variable2String(aVariables[iVar]));
410   }
411
412   //Add empty row
413   AddEmptyRow();
414   isProcessItemChangedSignal = true;
415
416   ResetMaps();
417 }
418
419 //============================================================================
420 /*! Function : Variable2String
421  *  Purpose  : Convert variable values to QString
422  */
423 //============================================================================
424 QString NoteBook_Table::Variable2String(const std::string& theVarName)
425 {
426   _PTR(Study) aStudy = SalomeApp_Application::getStudy();
427   QString aResult;
428   if( aStudy->IsReal(theVarName) )
429     aResult = QString::number(aStudy->GetReal(theVarName));
430   else if( aStudy->IsInteger(theVarName) )
431     aResult = QString::number(aStudy->GetInteger(theVarName));
432   else if( aStudy->IsBoolean(theVarName) )
433     aResult = aStudy->GetBoolean(theVarName) ? QString("True") : QString("False");
434   else if( aStudy->IsString(theVarName) )
435     aResult = aStudy->GetString(theVarName).c_str();
436   
437   return aResult;
438 }
439
440 //============================================================================
441 /*! Function : IsValid
442  *  Purpose  : Check validity of the table data
443  */
444 //============================================================================
445 bool NoteBook_Table::IsValid() const
446 {
447   int aNumRows = myRows.count();
448   if( aNumRows == 0 )
449     return true;
450
451   bool aLastRowIsEmpty = myRows[ aNumRows - 1 ]->GetName().isEmpty() &&
452                          myRows[ aNumRows - 1 ]->GetValue().isEmpty();
453
454   for( int i = 0, n = aLastRowIsEmpty ? aNumRows - 1 : aNumRows; i < n; i++ )
455     if( !myRows[i]->CheckName() || !IsUniqueName( myRows[i] ) || !myRows[i]->CheckValue() )
456       return false;
457
458   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
459   PyConsole_Console* pyConsole = app->pythonConsole();
460   PyConsole_Interp* pyInterp = app->getPyInterp();
461   PyLockWrapper aLock; // Acquire GIL
462   std::string command = "import salome_notebook ; ";
463   command += "salome_notebook.checkThisNoteBook(";
464   for( int i = 0, n = aLastRowIsEmpty ? aNumRows - 1 : aNumRows; i < n; i++ )
465     {
466       command += myRows[i]->GetName().toStdString();
467       command += "=\"";
468       command += myRows[i]->GetValue().toStdString();
469       command += "\",";
470     }
471   command += ")";
472
473   //rnv: fix for bug 21947 WinTC5.1.4: Wrong error management of "Salome NoteBook"
474   bool oldSuppressValue = pyConsole->isSuppressOutput();
475   pyConsole->setIsSuppressOutput(true); 
476   bool aResult = pyInterp->run(command.c_str());
477   pyConsole->setIsSuppressOutput(oldSuppressValue);     
478
479   return !aResult;
480 }
481
482 //============================================================================
483 /*! Function : RenumberRowItems
484  *  Purpose  : renumber row items
485  */
486 //============================================================================
487 void NoteBook_Table::RenumberRowItems() {
488   for(int i=0; i<myRows.size();i++){
489     myRows[i]->GetHeaderItem()->setText(QString::number(i+1));
490   }
491 }
492
493 //============================================================================
494 /*! Function : AddRow
495  *  Purpose  : Add a row into the table
496  */
497 //============================================================================
498 void NoteBook_Table::AddRow(const QString& theName, const QString& theValue)
499 {
500   int anIndex = getUniqueIndex();
501   NoteBook_TableRow* aRow = new NoteBook_TableRow(anIndex, this, this);
502   aRow->SetName(theName);
503   aRow->SetValue(theValue);
504   aRow->AddToTable(this);
505   myRows.append(aRow);
506
507   myVariableMap.insert( anIndex, NoteBoox_Variable( theName, theValue ) );
508 }
509
510 //============================================================================
511 /*! Function : AddEmptyRow
512  *  Purpose  : Add an empty row into the end of the table
513  */
514 //============================================================================
515 void NoteBook_Table::AddEmptyRow()
516 {
517   isProcessItemChangedSignal = false;
518   AddRow();
519   isProcessItemChangedSignal = true;
520 }
521
522 //============================================================================
523 /*! Function : GetRowByItem
524  *  Purpose  : 
525  */
526 //============================================================================
527 NoteBook_TableRow* NoteBook_Table::GetRowByItem(const QTableWidgetItem* theItem) const
528 {
529   int aCurrentRow = row(theItem);
530   
531   if( (myRows.size() <= aCurrentRow ) && (aCurrentRow < 0))
532     return NULL;
533   else
534     return myRows.at(aCurrentRow);
535 }
536
537 //============================================================================
538 /*! Function : IsLastRow
539  *  Purpose  : Return true if theRow is last row in the table
540  */
541 //============================================================================
542 bool NoteBook_Table::IsLastRow(const NoteBook_TableRow* theRow) const
543 {
544   return (myRows.last() == theRow);
545 }
546
547 //============================================================================
548 /*! Function : onItemChanged
549  *  Purpose  : [slot] called when table item changed
550  */
551 //============================================================================
552 void NoteBook_Table::onItemChanged(QTableWidgetItem* theItem)
553 {
554   if(isProcessItemChangedSignal) {
555     bool isModified = true;
556     NoteBook_TableRow* aRow = GetRowByItem(theItem);
557     if(aRow) {
558       int aCurrentColumn = column(theItem);
559       bool IsCorrect = true, IsVariableComplited = false;
560       QString aMsg;
561
562       if(aCurrentColumn == NAME_COLUMN) {
563         int anIndex = aRow->GetIndex();
564         if( myVariableMap.contains( anIndex ) )
565         {
566           const NoteBoox_Variable& aVariable = myVariableMap[ anIndex ];
567           if( !aVariable.Name.isEmpty() && SalomeApp_Application::getStudy()->IsVariableUsed( std::string( aVariable.Name.toUtf8().constData() ) ) )
568           {
569             if( QMessageBox::warning( parentWidget(), tr( "WARNING" ),
570                                       tr( "RENAME_VARIABLE_IS_USED" ).arg( aVariable.Name ),
571                                       QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
572             {
573               bool isBlocked = blockSignals( true );
574               aRow->SetName( aVariable.Name );
575               blockSignals( isBlocked );
576               return;
577             }
578           }
579         }
580       }
581
582       //Case when variable name was changed.
583       if(aCurrentColumn == NAME_COLUMN) {
584         if(!aRow->CheckName()) {
585           IsCorrect = false;
586           aMsg = tr( "VARNAME_INCORRECT" ).arg(aRow->GetName());
587         }
588         else if(!IsUniqueName(aRow)) {
589           IsCorrect = false;
590           aMsg = tr( "VARNAME_EXISTS" ).arg(aRow->GetName());
591         }
592         else
593           IsVariableComplited = aRow->CheckValue();
594       }
595       
596       //Case when variable value was changed. 
597       else if(aCurrentColumn == VALUE_COLUMN){
598         if(!aRow->CheckValue()) {
599           IsCorrect = false;
600           aMsg = tr( "VARVALUE_INCORRECT" ).arg(aRow->GetName());
601         }
602         else
603           IsVariableComplited = aRow->CheckName() && IsUniqueName(aRow);
604       }
605
606       if(!IsCorrect && !aMsg.isEmpty())
607         SUIT_MessageBox::warning( parentWidget(), tr( "WARNING" ), aMsg );
608
609       bool isBlocked = blockSignals( true );
610       theItem->setForeground( QBrush( IsCorrect ? Qt::black : Qt::red ) );
611       blockSignals( isBlocked );
612
613       int anIndex = aRow->GetIndex();
614       if( myVariableMap.contains( anIndex ) )
615       {
616         NoteBoox_Variable& aVariable = myVariableMap[ anIndex ];
617         if( aVariable.Name.compare( aRow->GetName() ) != 0 ||
618             aVariable.Value.compare( aRow->GetValue() ) != 0 )
619         {
620           aVariable.Name = aRow->GetName();
621           aVariable.Value = aRow->GetValue();
622         }
623         else
624           isModified = false;
625       }
626
627       if(IsCorrect && IsVariableComplited && IsLastRow(aRow))
628         AddEmptyRow();
629
630       if( aRow->CheckName() && aRow->CheckValue() )
631         qobject_cast<SalomeApp_NoteBook*>(parentWidget())->onApply();
632     }
633
634     if( !myIsModified )
635       myIsModified = isModified;
636   }
637 }
638
639 //============================================================================
640 /*! Function : IsUniqueName
641  *  Purpose  : Return true if theName is unique name of the Variable
642  */
643 //============================================================================
644 bool NoteBook_Table::IsUniqueName(const NoteBook_TableRow* theRow) const
645 {
646   for(int i=0; i<myRows.size();i++) {
647     if(myRows[i] == theRow ) 
648       continue;
649     if(myRows[i]->GetName().compare(theRow->GetName()) == 0)
650       return false;
651   }
652   return true;
653 }
654
655 //============================================================================
656 /*! Function : RemoveSelected
657  *  Purpose  : Remove selected rows in the table
658  */
659 //============================================================================
660 void NoteBook_Table::RemoveSelected()
661 {
662   _PTR(Study) aStudy = SalomeApp_Application::getStudy();
663   isProcessItemChangedSignal = false;
664   QList<QTableWidgetItem*> aSelectedItems = selectedItems();
665   if( !(aSelectedItems.size() > 0)) {
666     isProcessItemChangedSignal = true;
667     return;
668   }
669   bool removedFromStudy = false;
670   for(int i=0; i < aSelectedItems.size(); i++ ) {
671     NoteBook_TableRow* aRow = GetRowByItem(aSelectedItems[i]);
672     if(aRow) {
673       if(IsLastRow(aRow)) {
674         aRow->SetName(QString());
675         aRow->SetValue(QString());
676       }
677       else {
678         int nRow = row(aSelectedItems[i]);
679
680         if( aStudy->IsVariableUsed( std::string( aRow->GetName().toUtf8().constData() ) ) )
681         {
682           if( QMessageBox::warning( parentWidget(), tr( "WARNING" ),
683                                     tr( "REMOVE_VARIABLE_IS_USED" ).arg( aRow->GetName() ),
684                                     QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
685           {
686             isProcessItemChangedSignal = true;
687             return;
688           }
689         }
690
691         int index = aRow->GetIndex();
692         QString aVarName = aRow->GetName();
693         myRemovedRows.append( index );
694         if( myVariableMap.contains( index ) )
695           myVariableMap.remove( index );
696         removeRow(nRow);
697         myRows.removeAt(nRow);
698         if(aStudy->IsVariable(aVarName.toUtf8().constData()))
699           removedFromStudy = true;
700       }
701     }
702   }
703   if(removedFromStudy)
704     myIsModified = true;
705   RenumberRowItems();
706   isProcessItemChangedSignal = true;
707 }
708
709 //============================================================================
710 /*! Function : SetProcessItemChangedSignalFlag
711  *  Purpose  : 
712  */
713 //============================================================================
714 void NoteBook_Table::SetProcessItemChangedSignalFlag(const bool enable)
715 {
716   isProcessItemChangedSignal = enable;
717 }
718
719 //============================================================================
720 /*! Function : GetProcessItemChangedSignalFlag
721  *  Purpose  : 
722  */
723 //============================================================================
724 bool NoteBook_Table::GetProcessItemChangedSignalFlag() const
725 {
726   return isProcessItemChangedSignal;
727 }
728
729 //============================================================================
730 /*! Function : GetRows
731  *  Purpose  : 
732  */
733 //============================================================================
734 QList<NoteBook_TableRow*> NoteBook_Table::GetRows() const
735 {
736   return myRows;
737 }
738
739 //============================================================================
740 /*! Function : ResetMaps
741  *  Purpose  : Reset variable maps
742  */
743 //============================================================================
744 void NoteBook_Table::ResetMaps()
745 {
746   myIsModified = false;
747   myVariableMapRef = myVariableMap;
748   myRemovedRows.clear();
749 }
750
751 ///////////////////////////////////////////////////////////////////////////
752 //                  SalomeApp_NoteBook class                          //
753 ///////////////////////////////////////////////////////////////////////////
754 //============================================================================
755 /*! Function : SalomeApp_NoteBook
756  *  Purpose  : Constructor
757  */
758 //============================================================================
759 SalomeApp_NoteBook::SalomeApp_NoteBook(QWidget * parent):
760   QWidget(parent)
761 {
762   setObjectName("SalomeApp_NoteBook");
763   setWindowTitle(tr("NOTEBOOK_TITLE"));
764   QGridLayout* aLayout = new QGridLayout(this);
765
766   //Table
767   myTable = new NoteBook_Table(this);
768   aLayout->addWidget(myTable, 0, 0, 1, 3);
769   
770   //Buttons
771   myRemoveButton = new QPushButton(tr("BUT_REMOVE"));
772   aLayout->addWidget(myRemoveButton, 1, 0);
773
774   QSpacerItem* spacer =
775     new QSpacerItem(DEFAULT_SPACING, 5 , QSizePolicy::Expanding, QSizePolicy::Minimum);
776   aLayout->addItem(spacer, 1, 1);
777
778   myUpdateStudyBtn = new QPushButton(tr("BUT_UPDATE_STUDY"));
779   aLayout->addWidget(myUpdateStudyBtn, 1, 2);
780
781   QWidgetList aWidgetList;
782   aWidgetList.append( myTable );
783   aWidgetList.append( myUpdateStudyBtn );
784   aWidgetList.append( myRemoveButton );
785   Qtx::setTabOrder( aWidgetList );
786
787   connect( myUpdateStudyBtn, SIGNAL(clicked()), this, SLOT(onUpdateStudy()) );
788   connect( myRemoveButton, SIGNAL(clicked()), this, SLOT(onRemove()));
789   
790   myTable->Init();
791
792   myDumpedStudyScript = "";  
793   myIsDumpedStudySaved = false;
794 }
795
796 //============================================================================
797 /*! Function : ~SalomeApp_NoteBook
798  *  Purpose  : Destructor
799  */
800 //============================================================================
801 SalomeApp_NoteBook::~SalomeApp_NoteBook(){}
802
803
804 //============================================================================
805 /*! Function : Init()
806  *  Purpose  : init variable table
807  */
808 //============================================================================
809 void SalomeApp_NoteBook::Init(){
810   myTable->Init();
811 }
812
813
814 //============================================================================
815 /*! Function : onVarUpdate
816  *  Purpose  : [slot]
817  */
818 //============================================================================
819 void SalomeApp_NoteBook::onVarUpdate(QString /*theVarName*/)
820 {
821   myTable->Init();
822 }
823
824 //============================================================================
825 /*! Function : onApply
826  *  Purpose  : [slot]
827  */
828 //============================================================================
829 void SalomeApp_NoteBook::onApply()
830 {
831   if( !myTable->IsValid() )
832   {
833     SUIT_MessageBox::warning( this, tr( "WARNING" ), tr( "INCORRECT_DATA" ) );
834     return;
835   }
836   _PTR(Study) aStudy = SalomeApp_Application::getStudy();
837
838   double aDVal;
839   int    anIVal;
840   bool   aBVal;
841
842   const QList<int>& aRemovedRows = myTable->GetRemovedRows();
843   const VariableMap& aVariableMap = myTable->GetVariableMap();
844   const VariableMap& aVariableMapRef = myTable->GetVariableMapRef();
845
846   for( QListIterator<int> anIter( aRemovedRows ); anIter.hasNext(); )
847   {
848     int anIndex = anIter.next();
849     if( aVariableMapRef.contains( anIndex ) )
850     {
851       QString aRemovedVariable = aVariableMapRef[ anIndex ].Name;
852       aStudy->RemoveVariable( std::string( aRemovedVariable.toUtf8().constData() ) );
853     }
854   }
855
856   VariableMap::const_iterator it = aVariableMap.constBegin(), itEnd = aVariableMap.constEnd();
857   for( ; it != itEnd; ++it )
858   {
859     int anIndex = it.key();
860     const NoteBoox_Variable& aVariable = it.value();
861     QString aName = aVariable.Name;
862     QString aValue = aVariable.Value;
863
864     if( !aName.isEmpty() && !aValue.isEmpty() )
865     {
866       if( aVariableMapRef.contains( anIndex ) )
867       {
868         const NoteBoox_Variable& aVariableRef = aVariableMapRef[ anIndex ];
869         QString aNameRef = aVariableRef.Name;
870         QString aValueRef = aVariableRef.Value;
871
872         if( !aNameRef.isEmpty() && !aValueRef.isEmpty() && aNameRef != aName )
873         {
874           aStudy->RenameVariable( std::string( aNameRef.toUtf8().constData() ),
875                                   std::string( aName.toUtf8().constData() ) );
876         }
877       }
878
879       if( NoteBook_TableRow::IsIntegerValue(aValue,&anIVal) )
880         aStudy->SetInteger(std::string(aName.toUtf8().constData()),anIVal);
881
882       else if( NoteBook_TableRow::IsRealValue(aValue,&aDVal) )
883         aStudy->SetReal(std::string(aName.toUtf8().constData()),aDVal);
884     
885       else if( NoteBook_TableRow::IsBooleanValue(aValue,&aBVal) )
886         aStudy->SetBoolean(std::string(aName.toUtf8().constData()),aBVal);
887     
888       else
889         aStudy->SetString(std::string(aName.toUtf8().constData()),aValue.toStdString());
890     }
891   }
892   myTable->ResetMaps();
893
894   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
895   if(app)
896     app->updateActions();
897   
898   aStudy->Modified();
899 }
900
901 //============================================================================
902 /*! Function : onRemove
903  *  Purpose  : [slot]
904  */
905 //============================================================================
906 void SalomeApp_NoteBook::onRemove()
907 {
908   myTable->RemoveSelected();
909   onApply();
910 }
911
912 //============================================================================
913 /*! Function : onUpdateStudy
914  *  Purpose  : [slot]
915  */
916 //============================================================================
917 void SalomeApp_NoteBook::onUpdateStudy()
918 {
919   onApply();
920   if( !myTable->IsValid() )
921     return;
922   
923   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
924   if(!app)
925     return;
926   app->onUpdateStudy();
927 }