Salome HOME
Fix for the "0051899: curves are not shown in opened study" issue.
[modules/visu.git] / src / VISU_I / VISU_Table_i.cc
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  VISU OBJECT : interactive object for VISU entities implementation
24 //  File   : VISU_Table_i.cc
25 //  Author : Vadim SANDLER
26 //  Module : VISU
27 //
28 #include "VISU_Table_i.hh"
29
30 #include "VISU_Tools.h"
31 #include "VISU_CutLinesBase_i.hh"
32 #include "VISU_CutSegment_i.hh"
33 #include "VISU_Result_i.hh"
34 #include "VISU_ViewManager_i.hh"
35
36 #include "SALOME_Event.h"
37 #include "SPlot2d_Curve.h"
38
39 #include "VISU_TableReader.hxx"
40 #include "VISU_ConvertorUtils.hxx"
41
42 #include "utilities.h"
43
44 #include <Basics_Utils.hxx>
45
46 using namespace std;
47
48 #ifdef _DEBUG_
49 static int MYDEBUG = 0;
50 #else
51 static int MYDEBUG = 0;
52 #endif
53
54 //# Define delimeter
55 #define TLT_DLM ":"
56
57 //Absolute deviation
58 #define D_MIN "min"
59 #define D_MAX "max"
60
61 //Percentage deviation
62 #define D_PMIN "min%"
63 #define D_PMAX "max%"
64
65 #define D_EMIN "errmin"
66 #define D_EMAX "errmax"
67
68 #define D_EPMIN "errmin%"
69 #define D_EPMAX "errmax%"
70
71 #define D_ERR "error"
72 #define D_ERRP "error%"
73
74
75 //----------------------------------------------------------------
76 //                      Table Object
77 //----------------------------------------------------------------
78 int VISU::Table_i::myNbPresent = 0;
79 const string VISU::Table_i::myComment  = "TABLE";
80 /*!
81   Generate unique name
82 */
83 QString VISU::Table_i::GenerateName()
84 {
85   return VISU::GenerateName( "Table", ++myNbPresent );
86 }
87 /*!
88   Gets comment string
89 */
90 const char* VISU::Table_i::GetComment() const
91 {
92   return myComment.c_str();
93 }
94 /*!
95   Constructor
96 */
97 VISU::Table_i::Table_i( SALOMEDS::Study_ptr theStudy, const char* theObjectEntry )
98      : PrsObject_i(theStudy)
99 {
100   MESSAGE("Table_i::Table_i - "<<this);
101   mySObj = theStudy->FindObjectID(theObjectEntry);
102   myOrientation = VISU::Table::HORIZONTAL;
103   SetStudyDocument(theStudy);
104   BuildDeviationMap();
105 }
106 /*!
107   Destructor
108 */
109 VISU::Table_i::~Table_i()
110 {
111   MESSAGE("Table_i::~Table_i - "<<this);
112 }
113
114 //----------------------------------------------------------------------------
115 void
116 VISU::Table_i
117 ::SetTitle( const char* theTitle )
118 {
119   SetName( theTitle, true );
120 }
121
122 //----------------------------------------------------------------------------
123 char*
124 VISU::Table_i
125 ::GetTitle()
126 {
127   return CORBA::string_dup( GetName().c_str() );
128 }
129
130 //----------------------------------------------------------------------------
131 void
132 VISU::Table_i
133 ::SetOrientation( VISU::Table::Orientation theOrientation )
134 {
135   myOrientation = theOrientation;
136 }
137
138 //----------------------------------------------------------------------------
139 VISU::Table::Orientation
140 VISU::Table_i
141 ::GetOrientation()
142 {
143   return myOrientation;
144 }
145
146
147 //----------------------------------------------------------------------------
148 void
149 VISU::Table_i
150 ::SortRow(CORBA::Long theRow, VISU::SortOrder theSortOrder, VISU::SortPolicy theSortPolicy)
151 {
152   SALOMEDS::SObject_var SO = mySObj;
153   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
154   if ( !SO->_is_nil() ) {
155     SALOMEDS::GenericAttribute_var anAttr;
156     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
157       SALOMEDS::AttributeTableOfInteger_var anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
158       anInt->SortRow( theRow, (SALOMEDS::AttributeTable::SortOrder)theSortOrder,
159                       (SALOMEDS::AttributeTable::SortPolicy)theSortPolicy );
160     }
161     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
162       SALOMEDS::AttributeTableOfReal_var aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
163       aReal->SortRow( theRow, (SALOMEDS::AttributeTable::SortOrder)theSortOrder,
164                       (SALOMEDS::AttributeTable::SortPolicy)theSortPolicy );
165     }
166     UpdateCurves( std::map<int, int>() );
167   }
168 }
169
170 //----------------------------------------------------------------------------
171 void
172 VISU::Table_i
173 ::SortColumn(CORBA::Long theColumn, VISU::SortOrder theSortOrder, VISU::SortPolicy theSortPolicy)
174 {
175   SALOMEDS::SObject_var SO = mySObj;
176   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
177   if ( !SO->_is_nil() ) {
178     SALOMEDS::GenericAttribute_var anAttr;
179     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
180       SALOMEDS::AttributeTableOfInteger_var anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
181       anInt->SortColumn( theColumn, (SALOMEDS::AttributeTable::SortOrder)theSortOrder,
182                          (SALOMEDS::AttributeTable::SortPolicy)theSortPolicy );
183     }
184     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
185       SALOMEDS::AttributeTableOfReal_var aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
186       aReal->SortColumn( theColumn, (SALOMEDS::AttributeTable::SortOrder)theSortOrder,
187                          (SALOMEDS::AttributeTable::SortPolicy)theSortPolicy );
188     }
189     UpdateCurves( std::map<int, int>() );
190   }
191 }
192
193 //----------------------------------------------------------------------------
194 void
195 VISU::Table_i
196 ::SortByRow(CORBA::Long theRow, VISU::SortOrder theSortOrder, VISU::SortPolicy theSortPolicy)
197 {
198   SALOMEDS::SObject_var SO = mySObj;
199   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
200   if ( !SO->_is_nil() ) {
201     SALOMEDS::GenericAttribute_var anAttr;
202     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
203       SALOMEDS::AttributeTableOfInteger_var anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
204       anInt->SortByRow( theRow, (SALOMEDS::AttributeTable::SortOrder)theSortOrder,
205                         (SALOMEDS::AttributeTable::SortPolicy)theSortPolicy );
206     }
207     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
208       SALOMEDS::AttributeTableOfReal_var aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
209       aReal->SortByRow( theRow, (SALOMEDS::AttributeTable::SortOrder)theSortOrder,
210                         (SALOMEDS::AttributeTable::SortPolicy)theSortPolicy );
211     }
212     UpdateCurves( std::map<int, int>() );
213   }
214 }
215
216 //----------------------------------------------------------------------------
217 void
218 VISU::Table_i
219 ::SortByColumn(CORBA::Long theColumn, VISU::SortOrder theSortOrder, VISU::SortPolicy theSortPolicy)
220 {
221   SALOMEDS::SObject_var SO = mySObj;
222   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
223   if ( !SO->_is_nil() ) {
224     SALOMEDS::LongSeq_var aRowIndices;
225     SALOMEDS::GenericAttribute_var anAttr;
226     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
227       SALOMEDS::AttributeTableOfInteger_var anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
228       aRowIndices = anInt->SortByColumn( theColumn, (SALOMEDS::AttributeTable::SortOrder)theSortOrder,
229                                          (SALOMEDS::AttributeTable::SortPolicy)theSortPolicy );
230     }
231     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
232       SALOMEDS::AttributeTableOfReal_var aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
233       aRowIndices = aReal->SortByColumn( theColumn, (SALOMEDS::AttributeTable::SortOrder)theSortOrder,
234                                          (SALOMEDS::AttributeTable::SortPolicy)theSortPolicy );
235     }
236     std::map<int, int> aMixData;
237     for ( int i = 0, n = aRowIndices->length(); i < n; i++ )
238       aMixData[ aRowIndices[i] ] = i+1;
239     UpdateCurves( aMixData );
240   }
241 }
242
243 //----------------------------------------------------------------------------
244 void
245 VISU::Table_i
246 ::UpdateCurves(std::map<int,int> theMixData)
247 {
248   SALOMEDS::SObject_var SO = mySObj;
249   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
250   SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( SO );
251   for ( CI->InitEx( true ); CI->More(); CI->Next() ) {
252     CORBA::Object_var anObj = SObjectToObject( CI->Value() );
253     VISU::Curve_var aCurve = VISU::Curve::_narrow( anObj );
254     if ( !aCurve->_is_nil() ) {
255       if ( VISU::Curve_i* pCurve = dynamic_cast<VISU::Curve_i*>( GetServant( aCurve ).in() ) ) {
256         int aHRow = pCurve->GetHRow(), aVRow = pCurve->GetVRow();
257         if ( theMixData.find( aHRow ) != theMixData.end() )
258           pCurve->SetHRow( theMixData[ aHRow ] );
259         if ( theMixData.find( aVRow ) != theMixData.end() )
260           pCurve->SetVRow( theMixData[ aVRow ] );
261         UpdatePlot2d( pCurve, eUpdateData );
262       }
263     }
264   }
265 }
266 //----------------------------------------------------------------------------
267 bool 
268 VISU::Table_i::parseTitle(const QString theTitle, 
269                           QString& theOutTitle,
270                           DeviationType& theType, 
271                           bool& isMin) {
272   QStringList lst = theTitle.split(TLT_DLM);
273   theType = NoneDvtn;
274   isMin = false;
275   theOutTitle.clear();
276   if(lst.size() >= 2) {
277     QString s1 = lst[0];
278     QString s2 = lst[1];
279     if(QString::compare(lst[0], D_MIN, Qt::CaseInsensitive) == 0){
280       theType = AbsoluteDvtn;
281       isMin = true;
282     } else if(QString::compare(lst[0], D_MAX, Qt::CaseInsensitive) == 0) {
283       theType = AbsoluteDvtn;
284       isMin = false;
285     } else if(QString::compare(lst[0], D_PMIN, Qt::CaseInsensitive) == 0) {
286       theType = PercentageDvtn;
287       isMin = true;
288     } else if(QString::compare(lst[0], D_PMAX, Qt::CaseInsensitive) == 0) {
289       theType = PercentageDvtn;
290       isMin = false;
291     } else if(QString::compare(lst[0], D_EMIN, Qt::CaseInsensitive) == 0) {
292       theType = ErrorDvtn;
293       isMin = true;
294     } else if(QString::compare(lst[0], D_EMAX, Qt::CaseInsensitive) == 0) {
295       theType = ErrorDvtn;
296       isMin = false;
297     } else if(QString::compare(lst[0], D_EPMIN, Qt::CaseInsensitive) == 0) {
298       theType = ErrorPercentageDvtn;
299       isMin = true;
300     } else if(QString::compare(lst[0], D_EPMAX, Qt::CaseInsensitive) == 0) {
301       theType = ErrorPercentageDvtn;
302       isMin = false;
303     } else if(QString::compare(lst[0], D_ERR, Qt::CaseInsensitive) == 0) {
304       theType = SimpleErrorDvtn;
305     } else if(QString::compare(lst[0], D_ERRP, Qt::CaseInsensitive) == 0) {
306       theType = SimpleErrorPercentageDvtn;
307     }
308   }
309   if(theType == NoneDvtn){
310     return false;
311   } else {
312     for(int i = 1; i < lst.size();i++ )
313       theOutTitle += lst[i];
314     return true;
315   }
316 }
317 //----------------------------------------------------------------------------
318 double 
319 VISU::Table_i 
320 ::calculateDeviation(DeviationType theType, double value,double deviationValue, bool isMin){
321   double result;
322   switch(theType) {
323     case AbsoluteDvtn: 
324       result = deviationValue;
325       break;
326     case PercentageDvtn: 
327       result = value*deviationValue;
328       break;
329     case SimpleErrorDvtn:
330     case ErrorDvtn: 
331       result = value + (isMin ? -1.0 : 1.0)*deviationValue; 
332       break;
333     case ErrorPercentageDvtn:   
334     case SimpleErrorPercentageDvtn: 
335       result = value *( 1 + (isMin ? -1.0 : 1.0)*deviationValue); 
336       break;
337     default: result = 0.;
338   }
339   return isMin ? value - result : result - value;
340 }
341
342 QString 
343 VISU::Table_i
344 ::deviationLabel(DeviationData* info) {
345   QString lbl;
346   if(info) {
347       bool add = true;
348       switch(info->minDeviation()){
349         case SimpleErrorDvtn:
350           lbl = D_ERR;
351           add = false;
352           break;
353         case SimpleErrorPercentageDvtn:
354           lbl = D_ERRP;
355           add = false;
356           break;
357         case AbsoluteDvtn:
358           lbl = D_MIN;
359           break;
360         case PercentageDvtn:
361           lbl = D_PMIN;
362           break;
363         case ErrorDvtn:
364           lbl = D_EMIN;
365           break;
366         case ErrorPercentageDvtn:
367           lbl = D_EPMIN;
368           break;
369       }
370       if(add) {
371         lbl += " / ";
372         switch(info->maxDeviation()){
373           case AbsoluteDvtn:
374             lbl += D_MAX;
375             break;
376           case PercentageDvtn:
377             lbl += D_PMAX;
378             break;
379           case ErrorDvtn:
380             lbl += D_EMAX;
381             break;
382           case ErrorPercentageDvtn:
383             lbl += D_EPMAX;
384             break;
385         }
386       }
387   }
388   return lbl;
389 }
390
391 //----------------------------------------------------------------------------
392 bool
393 VISU::Table_i
394 ::hasDeviationData(const int row) {
395   return myDeviationMap.contains(row);
396 }
397
398 //----------------------------------------------------------------------------
399 VISU::DeviationData* 
400 VISU::Table_i::getDeviationInfo(const int row) {
401   if(hasDeviationData(row))
402     return &myDeviationMap[row];
403   return NULL;
404 }
405
406 //----------------------------------------------------------------------------
407 bool
408 VISU::Table_i
409 ::isDeviationRow(const int row) {
410   DeviationMap::const_iterator it = myDeviationMap.begin();
411   for( ; it != myDeviationMap.end(); it++) {
412     if((*it).minRow() == row || (*it).maxRow() == row)
413       return true;
414   }
415   return false;
416 }
417
418 //----------------------------------------------------------------------------
419 void
420 VISU::Table_i
421 ::BuildDeviationMap() {
422   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
423   SALOMEDS::GenericAttribute_var        anAttr;
424   SALOMEDS::AttributeTableOfInteger_var anInt;
425   SALOMEDS::AttributeTableOfReal_var    aReal;
426   SALOMEDS::StringSeq_var rowTitles = new SALOMEDS::StringSeq();
427   SALOMEDS::StringSeq_var rowUnits = new SALOMEDS::StringSeq();
428
429   if ( !mySObj->_is_nil() ) {
430     if ( Builder->FindAttribute( mySObj, anAttr, "AttributeTableOfInteger" ) ) {
431       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
432       rowTitles = anInt->GetRowTitles();
433       rowUnits = anInt->GetRowUnits();
434     }
435     else if ( Builder->FindAttribute( mySObj, anAttr, "AttributeTableOfReal" ) ) {
436       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
437       rowTitles = aReal->GetRowTitles();
438       rowUnits = aReal->GetRowUnits();
439       }
440    }
441    int nbTitles = rowTitles->length();
442    int nbUnits = rowUnits->length();
443
444    QString realTitle;
445    DeviationType deviationType; 
446    bool isMin;
447
448    //Deviation candidates map:
449    //Key - title without keyword, pair { "deviation type" , "id of row" }
450    QMap<QString, QPair<DeviationType,int> > minCandidatesMap;
451    QMap<QString, QPair<DeviationType,int> > maxCandidatesMap;
452    QMap<QString, QPair<DeviationType,int> > CandidatesMap;
453    if( nbTitles > 0 ) {
454      for(int i = 0; i < nbTitles; i++ ) {
455        if(parseTitle(rowTitles[i].in(), realTitle, deviationType, isMin)) {
456          if( deviationType == SimpleErrorDvtn || deviationType == SimpleErrorPercentageDvtn ){
457            if(!CandidatesMap.contains(realTitle)) {
458               CandidatesMap[realTitle] = QPair<DeviationType, int>(deviationType,i);
459            } else {
460             minCandidatesMap.remove(realTitle);
461             maxCandidatesMap.remove(realTitle);
462             CandidatesMap.remove(realTitle);
463            }
464             continue;
465          }
466          if(isMin) {
467            if(!minCandidatesMap.contains(realTitle)){
468               minCandidatesMap[realTitle] = QPair<DeviationType, int>(deviationType,i);
469            } else {
470             minCandidatesMap.remove(realTitle);
471             maxCandidatesMap.remove(realTitle);
472             CandidatesMap.remove(realTitle);
473            }
474          } else {
475            if(!maxCandidatesMap.contains(realTitle)){
476               maxCandidatesMap[realTitle] = QPair<DeviationType, int>(deviationType,i);
477            } else {
478             minCandidatesMap.remove(realTitle);
479             maxCandidatesMap.remove(realTitle);
480             CandidatesMap.remove(realTitle);
481            }
482          }
483        }
484      }
485      QString currentTitle;
486      for(int i = 0; i < nbTitles; i++ ) {
487       currentTitle = rowTitles[i].in();
488       if(minCandidatesMap.contains(currentTitle) && maxCandidatesMap.contains(currentTitle)) {
489         //check for the units
490         if(nbUnits > 0) {
491           if(i < nbUnits) {
492             const char* s1 = rowUnits[i].in();
493             const char* s2 = rowUnits[minCandidatesMap[currentTitle].second].in();
494             const char* s3 = rowUnits[maxCandidatesMap[currentTitle].second].in();
495             if(strcmp(s1,s2) != 0 || strcmp(s1,s3) != 0 ) continue;
496           } else continue;
497         }
498         myDeviationMap[i] = DeviationData(minCandidatesMap[currentTitle].second,
499                                           maxCandidatesMap[currentTitle].second,
500                                           minCandidatesMap[currentTitle].first,
501                                           maxCandidatesMap[currentTitle].first);
502       } else if(CandidatesMap.contains(currentTitle)) {
503           //check for the units
504           if(nbUnits > 0) {
505             if(i < nbUnits) {
506               const char* s1 = rowUnits[i].in();
507               const char* s2 = rowUnits[CandidatesMap[currentTitle].second].in();
508               if(strcmp(s1,s2) != 0) continue;
509             } else continue;
510           }
511           myDeviationMap[i] = DeviationData(CandidatesMap[currentTitle].second,
512                                           CandidatesMap[currentTitle].second,
513                                           CandidatesMap[currentTitle].first,
514                                           CandidatesMap[currentTitle].first);
515       }
516      }
517    }
518 }
519
520 //----------------------------------------------------------------------------
521 SALOMEDS::SObject_var
522 VISU::Table_i
523 ::GetSObject() const
524 {
525   return mySObj;
526 }
527
528 //----------------------------------------------------------------------------
529 std::string
530 VISU::Table_i
531 ::GetObjectEntry() 
532 {
533   CORBA::String_var anEntry = mySObj->GetID();
534   return anEntry.in(); 
535 }
536
537 //----------------------------------------------------------------------------
538 /*!
539   Gets number of rows in table
540 */
541 CORBA::Long VISU::Table_i::GetNbRows()
542 {
543   SALOMEDS::SObject_var SO = mySObj;
544   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
545   if ( !SO->_is_nil() ) {
546     SALOMEDS::GenericAttribute_var        anAttr;
547     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
548       SALOMEDS::AttributeTableOfInteger_var anInt =  SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
549         return anInt->GetNbRows();
550     }
551     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
552       SALOMEDS::AttributeTableOfReal_var aReal =  SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
553       return aReal->GetNbRows();
554     }
555   }
556   return 0;
557 }
558 /*!
559   Gets number of columns in table
560 */
561 CORBA::Long VISU::Table_i::GetNbColumns()
562 {
563   SALOMEDS::SObject_var SO = mySObj;
564   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
565   if ( !SO->_is_nil() ) {
566     SALOMEDS::GenericAttribute_var        anAttr;
567     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
568       SALOMEDS::AttributeTableOfInteger_var anInt =  SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
569       return anInt->GetNbColumns();
570     }
571     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
572       SALOMEDS::AttributeTableOfReal_var aReal =  SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
573       return aReal->GetNbColumns();
574     }
575   }
576   return 0;
577 }
578 /*!
579   Creates table object
580 */
581 VISU::Storable* VISU::Table_i::Create()
582 {
583   // generate name ...
584   SetName(GetTableTitle().toLatin1().data(), false);
585
586   // mpv (PAL 5357): if name attribute already exist at this label, use it as name of table
587   if ( GetName() == "" )
588     if ( !mySObj->_is_nil() ) {
589       CutLinesBase_i* pCutLines = NULL;
590       CORBA::Object_var anObj = SObjectToObject(mySObj);
591       if(!CORBA::is_nil(anObj)){
592         VISU::CutLinesBase_var aCutLines = VISU::CutLinesBase::_narrow(anObj);
593           if(!aCutLines->_is_nil())
594             pCutLines = dynamic_cast<CutLinesBase_i*>(GetServant(aCutLines).in());
595         }
596       if (!pCutLines)
597         if (mySObj->GetName()) SetName(mySObj->GetName(), false);
598     }
599
600   if ( GetName() == "" )
601     SetName(GenerateName().toLatin1().data(), false);
602   // ... and build the object
603   return Build( false );
604 }
605 /*!
606   Builds presentation of table
607 */
608 VISU::Storable* VISU::Table_i::Build( int theRestoring )
609 {
610
611   // look for reference SObject with table attribute
612   SALOMEDS::SObject_var SO = mySObj;
613
614   if ( !SO->_is_nil() ) {
615     CutLinesBase_i* pCutLines = NULL;
616     CORBA::Object_var anObj = SObjectToObject(SO);
617     if(!CORBA::is_nil(anObj)){
618       VISU::CutLinesBase_var aCutLines = VISU::CutLinesBase::_narrow(anObj);
619       if(!aCutLines->_is_nil())
620         pCutLines = dynamic_cast<CutLinesBase_i*>(GetServant(aCutLines).in());
621     }
622     SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
623     SALOMEDS::GenericAttribute_var anAttr;
624     // look for component
625     if ( !theRestoring ) {
626       SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
627       // create SObject and set attributes
628       QString aComment;
629       if(pCutLines)
630         aComment.sprintf("myComment=%s;mySourceId=CutLines",GetComment());
631       else{
632         aComment.sprintf("myComment=%s;mySourceId=TableAttr",GetComment());
633         SALOMEDS::SObject_var aFatherSObject = SO->GetFather();
634         if(aFatherSObject->FindAttribute(anAttr,"AttributeString")){
635           SALOMEDS::AttributeString_var aCommentAttr =
636             SALOMEDS::AttributeString::_narrow(anAttr);
637           CORBA::String_var aValue = aCommentAttr->Value();
638           Storable::TRestoringMap aMap;
639           Storable::StringToMap(aValue.in(),aMap);
640           bool anIsExist;
641           QString aMethodName = VISU::Storable::FindValue(aMap,"myComment",&anIsExist);
642           if(anIsExist){
643             if( aMethodName == "ImportTables" ){
644               aComment.sprintf("myComment=%s;mySourceId=TableFile",GetComment());
645             }
646           }
647         }
648       }
649
650       string anEntry = CreateAttributes( GetStudyDocument(),
651                                          SO->GetID(),//SComponent->GetID(),
652                                          "ICON_TREE_TABLE",
653                                          GetID(),
654                                          GetName(),
655                                          "",
656                                          aComment.toLatin1().data(),
657                                          pCutLines );
658       // create SObject referenced to real table object
659       mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID( anEntry.c_str() ));
660       if(pCutLines) {
661         bool isCutSegment = dynamic_cast<CutSegment_i*>(pCutLines);
662         pCutLines->BuildTableOfReal(mySObj, isCutSegment);
663       }
664       // mpv (PAL5357): reference attributes are unnecessary now
665       //SALOMEDS::SObject_var refSO = Builder->NewObject( mySObj );
666       //Builder->Addreference( refSO, SO );
667     }
668
669     return this;
670   }
671   return NULL;
672 }
673 /*!
674   Restores table object from stream
675 */
676 VISU::Storable* VISU::Table_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr SO)
677 {
678   if(MYDEBUG) MESSAGE(GetComment());
679   SetName(VISU::Storable::FindValue(theMap,"myName").toLatin1().data(), false);
680   myTitle = VISU::Storable::FindValue(theMap,"myTitle").toLatin1().data();
681   myOrientation = ( VISU::Table::Orientation )( VISU::Storable::FindValue(theMap,"myOrientation").toInt() );
682   mySObj = SALOMEDS::SObject::_duplicate(SO);
683   mySObj->Register();
684   return Build( true );
685 }
686 /*!
687   Flushes table data into stream
688 */
689 void VISU::Table_i::ToStream( std::ostringstream& theStr )
690 {
691   Storable::DataToStream( theStr, "myName",        GetName().c_str() );
692   Storable::DataToStream( theStr, "myTitle",       myTitle.c_str() );
693   Storable::DataToStream( theStr, "myOrientation", myOrientation );
694 }
695 /*!
696   Called from engine to restore table from the file
697 */
698 VISU::Storable* VISU::Table_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
699                                               const Storable::TRestoringMap& theMap,
700                                               const std::string& thePrefix,
701                                               CORBA::Boolean theIsMultiFile)
702 {
703   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
704   VISU::Table_i* pResent = new VISU::Table_i( aStudy, "" );
705   return pResent->Restore( theMap, theSObject);
706 }
707 /*!
708   Gets title for the original table object
709 */
710 QString VISU::Table_i::GetTableTitle()
711 {
712   SALOMEDS::SObject_var SO = mySObj;
713   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
714   SALOMEDS::GenericAttribute_var        anAttr;
715   SALOMEDS::AttributeTableOfInteger_var anInt;
716   SALOMEDS::AttributeTableOfReal_var    aReal;
717   if ( !SO->_is_nil() ) {
718     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
719       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
720       CORBA::String_var aString = anInt->GetTitle();
721       return aString.in();
722     }
723     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
724       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
725       CORBA::String_var aString = aReal->GetTitle();
726       return aString.in();
727     }
728   }
729   return "";
730 }
731
732 //---------------------------------------------------------------
733 void VISU::Table_i::RemoveFromStudy()
734 {
735   struct TRemoveFromStudy: public SALOME_Event
736   {
737     VISU::Table_i* myRemovable;
738     TRemoveFromStudy(VISU::Table_i* theRemovable):
739       myRemovable(theRemovable)
740     {}
741     
742     virtual
743     void
744     Execute()
745     {
746       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
747     }
748   };
749
750   // Remove the table with all curves
751   ProcessVoidEvent(new TRemoveFromStudy(this));
752 }
753
754 //----------------------------------------------------------------
755 //                      Curve Object
756 //----------------------------------------------------------------
757 /*!
758   Restores table object from the stream [ static ]
759 */
760 static VISU::Table_i* GetTable( SALOMEDS::Study_ptr theStudy, SALOMEDS::SObject_ptr theSO ) {
761   CORBA::Object_var anObject = VISU::SObjectToObject( theSO );
762   if( !CORBA::is_nil( anObject ) ) {
763     CORBA::Object_ptr aTable = VISU::Table::_narrow( anObject );
764     if( !CORBA::is_nil( aTable ) )
765       return dynamic_cast<VISU::Table_i*>(VISU::GetServant(aTable).in());
766   }
767   return NULL;
768 }
769
770 int VISU::Curve_i::myNbPresent = 0;
771 const string VISU::Curve_i::myComment  = "CURVE";
772 /*!
773   Generate unique name
774 */
775 QString VISU::Curve_i::GenerateName()
776 {
777   return VISU::GenerateName( "Curve", ++myNbPresent ).toLatin1().data();
778 }
779 /*!
780   Gets comment string
781 */
782 const char* VISU::Curve_i::GetComment() const
783 {
784   return myComment.c_str();
785 }
786 /*!
787   Constructor
788   NB : theHRow, theVRow are the indexes of rows in the Table object and numbered from the 1 to GetNbRows()
789 */
790 VISU::Curve_i::Curve_i( SALOMEDS::Study_ptr theStudy, Table_i* theTable,
791                         CORBA::Long theHRow, CORBA::Long theVRow,
792                         CORBA::Long theZRow, CORBA::Boolean theIsV2 )
793 : PrsObject_i(theStudy), myTable( theTable ), myHRow( theHRow ),
794   myVRow( theVRow ), myZRow( theZRow ), myIsV2( theIsV2 ), myDeviationEnabled(false)
795 {
796   myAuto = true;
797   myLine = VISU::Curve::SOLIDLINE;
798   myLineWidth = 0;
799   myMarker = VISU::Curve::CIRCLE;
800   myColor.R = 0.0; myColor.G = 0.0; myColor.B = 0.0;
801   myScale = 1.0;
802 }
803 /*!
804   Destructor
805 */
806 VISU::Curve_i::~Curve_i()
807 {
808   MESSAGE("Curve_i::~Curve_i");
809 }
810
811 //----------------------------------------------------------------------------
812 void
813 VISU::Curve_i
814 ::SetTitle( const char* theTitle )
815 {
816   SetName( theTitle, true );
817 }
818
819 //----------------------------------------------------------------------------
820 char*
821 VISU::Curve_i
822 ::GetTitle()
823 {
824   return CORBA::string_dup( GetName().c_str() );
825 }
826
827 //----------------------------------------------------------------------------
828 void
829 VISU::Curve_i
830 ::SetColor( const SALOMEDS::Color& theColor )
831 {
832   myColor = theColor; 
833   myAuto = false;
834 }
835
836 //----------------------------------------------------------------------------
837 SALOMEDS::Color
838 VISU::Curve_i
839 ::GetColor()
840 {
841   return myColor;
842 }
843
844 //----------------------------------------------------------------------------
845 void
846 VISU::Curve_i
847 ::SetMarker( VISU::Curve::MarkerType theType )
848 {
849   myMarker = theType; 
850   myAuto = false;
851 }
852
853 //----------------------------------------------------------------------------
854 VISU::Curve::MarkerType
855 VISU::Curve_i
856 ::GetMarker()
857 {
858   return myMarker;
859 }
860
861 //----------------------------------------------------------------------------
862 void
863 VISU::Curve_i
864 ::SetLine( VISU::Curve::LineType theType, CORBA::Long theWidth )
865 {
866   myLine = theType; 
867   myLineWidth = theWidth; 
868   myAuto = false;
869 }
870
871 //----------------------------------------------------------------------------
872 VISU::Curve::LineType
873 VISU::Curve_i
874 ::GetLine()
875 {
876   return myLine;
877 }
878
879 //----------------------------------------------------------------------------
880 CORBA::Long
881 VISU::Curve_i
882 ::GetLineWidth()
883 {
884   return myLineWidth;
885 }
886
887 //----------------------------------------------------------------------------
888 void 
889 VISU::Curve_i
890 ::SetScale( CORBA::Double theCoef )
891 {
892   myScale = theCoef;  
893   UpdatePlot2d( this, eUpdateData );
894 }
895
896 //----------------------------------------------------------------------------
897 CORBA::Double 
898 VISU::Curve_i
899 ::GetScale()
900 {
901   return myScale;    
902 }
903
904 //----------------------------------------------------------------------------
905 void 
906 VISU::Curve_i
907 ::RemoveScale()
908 {
909   SetScale( 1.0 );
910 }
911
912 //----------------------------------------------------------------------------
913 /*!
914   Creates curve object
915 */
916 VISU::Storable* VISU::Curve_i::Create()
917 {
918   // generate name ...
919   SetName(GetVerTitle(), false);
920   if ( GetName() == "" )
921     SetName(GenerateName().toLatin1().data(), false);
922   // ... and build the object
923   return Build( false );
924 }
925 /*!
926   Builds presentation of curve
927 */
928 VISU::Storable* VISU::Curve_i::Build(int theRestoring )
929 {
930   if ( myTable != NULL ) {
931     // getting table SObject by it's entry
932     int nbRows = myTable->GetNbRows();
933     if ( myHRow > 0 && myHRow <= nbRows && myVRow > 0 && myVRow <= nbRows ) {
934       if ( !theRestoring ) {
935         // look for component
936         SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
937         // create SObject and set attributes
938         QString aComment;
939         aComment.sprintf("myComment=%s",GetComment());
940         string anEntry = CreateAttributes( GetStudyDocument(),
941                                           myTable->GetObjectEntry(),
942                                           "",
943                                           GetID(),
944                                           GetName(),
945                                           "",
946                                           aComment.toLatin1().data(),
947                                           true );
948         // create SObject referenced to real table object
949         mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID(anEntry.c_str()));
950
951         // Set icon
952         SALOMEDS::StudyBuilder_var aStudyBuilder = GetStudyDocument()->NewBuilder();
953         SALOMEDS::GenericAttribute_var anAttr;
954         SALOMEDS::AttributePixMap_var  aPixmap;
955         anAttr  = aStudyBuilder->FindOrCreateAttribute( mySObj, "AttributePixMap" );
956         aPixmap = SALOMEDS::AttributePixMap::_narrow( anAttr );
957         aPixmap ->SetPixMap("ICON_TREE_CURVE");
958       }
959       return this;
960     }
961   }
962   return NULL;
963 }
964
965 /*!
966   Returns CORBA::True if curve refers to valid table data
967 */
968 CORBA::Boolean VISU::Curve_i::IsValid()
969 {
970   // getting table SObject by it's entry
971   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
972   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
973   SALOMEDS::GenericAttribute_var        anAttr;
974   SALOMEDS::AttributeTableOfInteger_var anInt;
975   SALOMEDS::AttributeTableOfReal_var    aReal;
976   if ( !SO->_is_nil() ) {
977     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
978       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
979       if ( myHRow > 0 && myHRow <= anInt->GetNbRows() && myVRow > 0 && myVRow <= anInt->GetNbRows() ) {
980         return true;
981       }
982     }
983     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
984       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
985       if ( myHRow > 0 && myHRow <= aReal->GetNbRows() && myVRow > 0 && myVRow <= aReal->GetNbRows() ) {
986         return true;
987       }
988     }
989   }
990   return false;
991 }
992 /*!
993   Returns hor.axis title
994 */
995 string VISU::Curve_i::GetHorTitle()
996 {
997   string title;
998   // getting table SObject by it's entry
999   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1000   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1001   SALOMEDS::GenericAttribute_var        anAttr;
1002   SALOMEDS::AttributeTableOfInteger_var anInt;
1003   SALOMEDS::AttributeTableOfReal_var    aReal;
1004   if ( !SO->_is_nil() ) {
1005     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1006       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1007       SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
1008       if ( rowTitles->length() > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() ) {
1009         title = rowTitles[ myHRow-1 ];
1010       }
1011     }
1012     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1013       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1014       SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
1015       if ( rowTitles->length() > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() ) {
1016         title = rowTitles[ myHRow-1 ];
1017       }
1018     }
1019   }
1020   return title;
1021 }
1022 /*!
1023   Returns ver.axis title
1024 */
1025 string VISU::Curve_i::GetVerTitle()
1026 {
1027   string title;
1028   // getting table SObject by it's entry
1029   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1030   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1031   SALOMEDS::GenericAttribute_var        anAttr;
1032   SALOMEDS::AttributeTableOfInteger_var anInt;
1033   SALOMEDS::AttributeTableOfReal_var    aReal;
1034   if ( !SO->_is_nil() ) {
1035     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1036       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1037       SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
1038       if ( rowTitles->length() > 0 && myVRow > 0 && myVRow <= anInt->GetNbRows() )
1039         title = rowTitles[ myVRow-1 ];
1040     }
1041     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1042       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1043       SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
1044       if ( rowTitles->length() > 0 && myVRow > 0 && myVRow <= aReal->GetNbRows() )
1045         title = rowTitles[ myVRow-1 ];
1046     }
1047   }
1048   return title;
1049 }
1050 /*!
1051   Returns hor.axis units
1052 */
1053 string VISU::Curve_i::GetHorUnits()
1054 {
1055   string units;
1056   // getting table SObject by it's entry
1057   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1058   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1059   SALOMEDS::GenericAttribute_var        anAttr;
1060   SALOMEDS::AttributeTableOfInteger_var anInt;
1061   SALOMEDS::AttributeTableOfReal_var    aReal;
1062   if ( !SO->_is_nil()  ) {
1063     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1064       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1065       SALOMEDS::StringSeq_var rowUnits = anInt->GetRowUnits();
1066       if ( rowUnits->length() > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() )
1067         units = rowUnits[ myHRow-1 ];
1068     }
1069     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1070       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1071       SALOMEDS::StringSeq_var rowUnits = aReal->GetRowUnits();
1072       if ( rowUnits->length() > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() )
1073         units = rowUnits[ myHRow-1 ];
1074     }
1075   }
1076   return units;
1077 }
1078 /*!
1079   Returns ver.axis units
1080 */
1081 string VISU::Curve_i::GetVerUnits()
1082 {
1083   string units;
1084   // getting table SObject by it's entry
1085   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1086   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1087   SALOMEDS::GenericAttribute_var        anAttr;
1088   SALOMEDS::AttributeTableOfInteger_var anInt;
1089   SALOMEDS::AttributeTableOfReal_var    aReal;
1090   if ( !SO->_is_nil() ) {
1091     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1092       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1093       SALOMEDS::StringSeq_var rowUnits = anInt->GetRowUnits();
1094       if ( rowUnits->length() > 0 && myVRow > 0 && myVRow <= anInt->GetNbRows() )
1095         units = rowUnits[ myVRow-1];
1096     }
1097     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1098       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1099       SALOMEDS::StringSeq_var rowUnits = aReal->GetRowUnits();
1100       if ( rowUnits->length() > 0 && myVRow > 0 && myVRow <= aReal->GetNbRows() )
1101         units = rowUnits[ myVRow-1 ];
1102     }
1103   }
1104   return units;
1105 }
1106 /*!
1107   Gets curve data
1108 */
1109 int VISU::Curve_i::GetData( double*& theHorList, double*& theVerList, QStringList& zList )
1110 {
1111   theHorList = 0; theVerList = 0;
1112   // getting table SObject by it's entry
1113   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1114   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1115   SALOMEDS::GenericAttribute_var        anAttr;
1116   SALOMEDS::AttributeTableOfInteger_var anInt;
1117   SALOMEDS::AttributeTableOfReal_var    aReal;
1118
1119   QString tip = "%1: %2", z_data;
1120
1121   if ( !SO->_is_nil() ) {
1122     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1123       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1124       int nbCols = anInt->GetNbColumns(), nbRows = anInt->GetNbRows();
1125       if ( nbCols > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() && myVRow > 0 && myVRow <= anInt->GetNbRows() ) {
1126         int nbPoints = 0;
1127         for ( int j = 1; j <= nbCols; j++ ) {
1128           if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) )
1129             nbPoints++;
1130         }
1131         if ( nbPoints > 0 ) {
1132           theHorList = new double[ nbPoints ];
1133           theVerList = new double[ nbPoints ];
1134           int k = 0;
1135
1136           SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
1137
1138           for ( int j = 1; j <= nbCols; j++ ) {
1139             if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) ) {
1140               theHorList[k] = anInt->GetValue( myHRow, j );
1141               theVerList[k] = anInt->GetValue( myVRow, j );
1142
1143               z_data = tip.arg( GetHorTitle().c_str() ).arg( theHorList[k] ) + "\n";
1144               z_data += tip.arg( GetVerTitle().c_str() ).arg( theVerList[k] );
1145
1146               if( myZRow>0 && myZRow<=nbRows && anInt->HasValue( myZRow, j ) )
1147               {
1148                 string title;
1149                 title = rowTitles[ myZRow-1 ];
1150                 z_data += "\n" + tip.arg( title.c_str() ).arg( anInt->GetValue( myZRow, j ) );
1151               }
1152               zList.append( z_data );
1153               k++;
1154             }
1155           }
1156         }
1157         return nbPoints;
1158       }
1159     }
1160     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1161       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1162       int nbCols = aReal->GetNbColumns(), nbRows = aReal->GetNbRows();
1163       if ( nbCols > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() && myVRow > 0 && myVRow <= aReal->GetNbRows() ) {
1164         int nbPoints = 0;
1165         for ( int j = 1; j <= nbCols; j++ ) {
1166           if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) )
1167             nbPoints++;
1168         }
1169         if ( nbPoints > 0 ) {
1170           theHorList = new double[ nbPoints ];
1171           theVerList = new double[ nbPoints ];
1172           int k = 0;
1173
1174           SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
1175
1176           for ( int j = 1; j <= nbCols; j++ ) {
1177             if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) ) {
1178               theHorList[k] = aReal->GetValue( myHRow, j );
1179               theVerList[k] = aReal->GetValue( myVRow, j );
1180
1181               z_data = tip.arg( GetHorTitle().c_str() ).arg( theHorList[k] ) + "\n";
1182               z_data += tip.arg( GetVerTitle().c_str() ).arg( theVerList[k] );
1183
1184               if( myZRow>0 && myZRow<=nbRows && aReal->HasValue( myZRow, j ) )
1185               {
1186                 string title;
1187                 title = rowTitles[ myZRow-1 ];
1188                 z_data += "\n" + tip.arg( title.c_str() ).arg( aReal->GetValue( myZRow, j ) );
1189               }
1190               zList.append( z_data );
1191               k++;
1192             }
1193           }
1194         }
1195         return nbPoints;
1196       }
1197     }
1198   }
1199   return 0;
1200 }
1201
1202 int VISU::Curve_i::GetDeviationData( double*& theMin, double*& theMax, QList<int>& theIndexes) {
1203   if(!hasDeviation())
1204     return 0;
1205
1206   theIndexes.clear();
1207
1208   DeviationData *info = myTable->getDeviationInfo(myVRow - 1);
1209   int minRow = info->minRow() + 1;
1210   int maxRow = info->maxRow() + 1;
1211
1212   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1213   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1214   SALOMEDS::GenericAttribute_var        anAttr;
1215   SALOMEDS::AttributeTableOfInteger_var anInt;
1216   SALOMEDS::AttributeTableOfReal_var    aReal;
1217
1218   int nbPoints = 0;
1219   if ( !SO->_is_nil() ) {
1220     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1221       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1222       int nbCols = anInt->GetNbColumns();
1223       int nbRows = anInt->GetNbRows();
1224       if ( nbCols > 0 && myHRow > 0 && myVRow && minRow > 0 && maxRow > 0 && 
1225            myHRow <= nbRows &&  myVRow <= nbRows && minRow <= nbRows && maxRow <= nbRows ) {
1226         for ( int j = 1; j <= nbCols; j++ ) {
1227                 if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) && 
1228                anInt->HasValue( minRow, j ) && anInt->HasValue( maxRow, j ) )
1229                   nbPoints++;
1230         }
1231
1232           if ( nbPoints > 0 ) {
1233                 theMin = new double[ nbPoints ];
1234                 theMax = new double[ nbPoints ];
1235             int k = 0;
1236           int value;
1237                 for ( int j = 1; j <= nbCols; j++ ) {
1238                   if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) &&
1239                  anInt->HasValue( minRow, j ) && anInt->HasValue( maxRow, j )) {
1240                  value = anInt->GetValue(myVRow,j);
1241               theMin[k] = Table_i::calculateDeviation(info->minDeviation(),value, anInt->GetValue(minRow,j), true);
1242                     theMax[k] = Table_i::calculateDeviation(info->maxDeviation(),value, anInt->GetValue(maxRow,j), false);
1243               k++;
1244               theIndexes.push_back(j-1);
1245             }
1246           } // for ( ...
1247         } // nbPoints > 0
1248       } // nbCols > 0 && myHRow > 0 && myVRow ...
1249     } // Builder->FindAttribute(...
1250     else if( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1251       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1252       int nbCols = aReal->GetNbColumns();
1253       int nbRows = aReal->GetNbRows();
1254       if ( nbCols > 0 && myHRow > 0 && myVRow && minRow > 0 && maxRow > 0 && 
1255            myHRow <= nbRows &&  myVRow <= nbRows && minRow <= nbRows && maxRow <= nbRows) {
1256         for ( int j = 1; j <= nbCols; j++ ) {
1257                 if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) && 
1258                aReal->HasValue( minRow, j ) && aReal->HasValue( maxRow, j ) )
1259                   nbPoints++;
1260         }
1261
1262           if ( nbPoints > 0 ) {
1263                 theMin = new double[ nbPoints ];
1264                 theMax = new double[ nbPoints ];
1265             int k = 0;
1266           double value;
1267                 for ( int j = 1; j <= nbCols; j++ ) {
1268                   if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) &&
1269                  aReal->HasValue( minRow, j ) && aReal->HasValue( maxRow, j )) {
1270               value =  aReal->GetValue(myVRow,j);
1271               theMin[k] = Table_i::calculateDeviation(info->minDeviation(),value, aReal->GetValue(minRow,j), true);
1272               theMax[k] = Table_i::calculateDeviation(info->maxDeviation(),value, aReal->GetValue(maxRow,j), false);
1273               k++;
1274               theIndexes.push_back(j-1);
1275             }
1276           } // for ( ..
1277         } // nbPoints > 0
1278       } // nbCols > 0 && myHRow > 0 && myVRow ...
1279     } // Builder->FindAttribute( ...
1280   } // !SO->_is_nil()
1281   return nbPoints;
1282 }
1283 /*!
1284   Creates curve Plot2d presentation object
1285 */
1286 SPlot2d_Curve* VISU::Curve_i::CreatePresentation()
1287 {
1288   SPlot2d_Curve* crv = new SPlot2d_Curve();
1289   crv->setYAxis( myIsV2 ? QwtPlot::yRight : QwtPlot::yLeft );
1290   crv->setHorTitle( GetHorTitle().c_str() );
1291   string tlt = GetTitle();
1292   if ( tlt.length() <= 0 )
1293     tlt = GetVerTitle();
1294   //crv->setVerTitle( strdup( GetVerTitle().c_str() ) );
1295   //crv->setVerTitle( strdup( GetName() ) );
1296   crv->setVerTitle( tlt.c_str() );
1297   crv->setHorUnits( GetHorUnits().c_str() );
1298   crv->setVerUnits( GetVerUnits().c_str() );
1299   double* xList = 0;
1300   double* yList = 0;
1301   QStringList zList;
1302   int     nbPoints = GetData( xList, yList, zList );
1303   if ( nbPoints > 0 && xList && yList ) {
1304     crv->setData( xList, yList, nbPoints, zList );
1305   }
1306   //cout << "********** Number of points: " << nbPoints <<endl;
1307   //for ( int i =0 ; i < nbPoints; i++ ) {
1308   //  cout << i<<"\t"<<xList[i] << "\t"<< yList[i] << endl;
1309   //}
1310   crv->setLine( (Plot2d::LineType)GetLine(), GetLineWidth() );
1311   crv->setMarker( (Plot2d::MarkerType)GetMarker() );
1312   SALOMEDS::Color color = GetColor();
1313   crv->setColor( QColor( (int)(color.R*255.), (int)(color.G*255.), (int)(color.B*255.) ) );
1314   crv->setAutoAssign( IsAuto() );
1315   CORBA::String_var aString = mySObj->GetID();
1316   crv->setIO(new SALOME_InteractiveObject(aString.in(), "VISU", GetName().c_str()));
1317   if ( myTable )
1318     crv->setTableIO(new SALOME_InteractiveObject(myTable->GetObjectEntry().c_str(), "VISU", myTable->GetName().c_str()));
1319
1320   if(!myContainers.isEmpty())     
1321     crv->addOwners(myContainers);
1322   return crv;
1323 }
1324 /*!
1325   Restores curve object from stream
1326 */
1327 VISU::Storable* VISU::Curve_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr theSO)
1328 {
1329   if(MYDEBUG) MESSAGE(GetComment());
1330   mySObj = SALOMEDS::SObject::_duplicate(theSO);
1331   mySObj->Register();
1332   SetName(VISU::Storable::FindValue(theMap,"myName").toLatin1().data(), false);
1333   myHRow = VISU::Storable::FindValue(theMap,"myHRow").toInt();
1334   myVRow = VISU::Storable::FindValue(theMap,"myVRow").toInt();
1335   bool ok = false;
1336   QString z_str = VISU::Storable::FindValue(theMap,"myZRow", &ok);
1337   myZRow = ok ? z_str.toInt() : 0;
1338   ok = false;
1339   QString v2_str = VISU::Storable::FindValue(theMap,"myIsV2", &ok);
1340   myIsV2 = ok ? v2_str.toInt() : false;
1341
1342   QString scale_str = VISU::Storable::FindValue(theMap,"myScale", &ok);
1343   myScale = ok ? scale_str.toDouble() : 1.0;
1344   myColor.R = VISU::Storable::FindValue(theMap,"myColor.R").toDouble();
1345   myColor.G = VISU::Storable::FindValue(theMap,"myColor.G").toDouble();
1346   myColor.B = VISU::Storable::FindValue(theMap,"myColor.B").toDouble();
1347   myMarker = ( VISU::Curve::MarkerType )( VISU::Storable::FindValue(theMap,"myMarker").toInt() );
1348   myLine = ( VISU::Curve::LineType )( VISU::Storable::FindValue(theMap,"myLine").toInt() );
1349   myLineWidth = VISU::Storable::FindValue(theMap,"myLineWidth").toInt();
1350   myAuto = VISU::Storable::FindValue(theMap,"myAuto").toInt();
1351   return Build( true );
1352 }
1353 /*!
1354   Flushes curve data into stream
1355 */
1356 void VISU::Curve_i::ToStream( std::ostringstream& theStr )
1357 {
1358   Storable::DataToStream( theStr, "myName",      GetName().c_str() );
1359   Storable::DataToStream( theStr, "myHRow",      myHRow );
1360   Storable::DataToStream( theStr, "myVRow",      myVRow );
1361   Storable::DataToStream( theStr, "myZRow",      myZRow );
1362   Storable::DataToStream( theStr, "myIsV2",      myIsV2 );
1363   Storable::DataToStream( theStr, "myScale",     myScale );
1364   Storable::DataToStream( theStr, "myColor.R",   myColor.R );
1365   Storable::DataToStream( theStr, "myColor.G",   myColor.G );
1366   Storable::DataToStream( theStr, "myColor.B",   myColor.B );
1367   Storable::DataToStream( theStr, "myMarker",    myMarker );
1368   Storable::DataToStream( theStr, "myLine",      myLine );
1369   Storable::DataToStream( theStr, "myLineWidth", myLineWidth );
1370   Storable::DataToStream( theStr, "myAuto",      myAuto );
1371 }
1372 /*!
1373   Gets reference table's entry
1374 */
1375 std::string VISU::Curve_i::GetTableID() {
1376   return myTable->GetObjectEntry();
1377 }
1378 /*!
1379   Called from engine to restore curve from the file
1380 */
1381 VISU::Storable* VISU::Curve_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
1382                                               const Storable::TRestoringMap& theMap,
1383                                               const std::string& thePrefix,
1384                                               CORBA::Boolean theIsMultiFile)
1385 {
1386   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
1387   VISU::Table_i* pTable = GetTable(aStudy, theSObject->GetFather());
1388   if( pTable != NULL ) {
1389     VISU::Curve_i* pResent = new VISU::Curve_i( aStudy, pTable, 0, 0, 0, false );
1390     return pResent->Restore( theMap, theSObject);
1391   }
1392   return NULL;
1393 }
1394
1395 void VISU::Curve_i::RemoveFromStudy()
1396 {
1397   
1398   //remove curve from containers
1399   PortableServer::POA_ptr aPOA = GetPOA();
1400   ContainerSet::ConstIterator it = myContainers.begin();
1401   for ( ; it != myContainers.end(); it++ ) {    
1402     SALOMEDS::SObject_var aSObject =  GetStudyDocument()->FindObjectID( (*it).toLatin1().data() );
1403     if ( aSObject->_is_nil() ) continue;
1404     
1405     CORBA::Object_var anObj = VISU::SObjectToObject( aSObject );
1406     if ( CORBA::is_nil( anObj ) ) continue;
1407     VISU::Container_i* aContainer = dynamic_cast<VISU::Container_i*>( VISU::GetServant( anObj.in() ).in() );
1408     if ( !aContainer ) continue;
1409     aContainer->RemoveCurve(VISU::Curve::_narrow(aPOA->servant_to_reference(this)));
1410   }
1411
1412   struct TRemoveFromStudy: public SALOME_Event
1413   {
1414     VISU::Curve_i* myRemovable;
1415     TRemoveFromStudy(VISU::Curve_i* theRemovable):
1416       myRemovable(theRemovable)
1417     {}
1418     
1419     virtual
1420     void
1421     Execute()
1422     {
1423       VISU::DeleteActors(myRemovable);
1424       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
1425     }
1426   };
1427
1428   ProcessVoidEvent(new TRemoveFromStudy(this));
1429 }
1430
1431 SALOMEDS::SObject_var VISU::Curve_i::GetSObject()
1432 {
1433   return mySObj;
1434 }
1435
1436
1437 /*!
1438   Add container.
1439   id  - owner of the curve
1440 */
1441 void VISU::Curve_i::addContainer(const QString& id) {
1442   myContainers.insert(id);
1443 }
1444
1445 /*!
1446   Remove Container
1447   id  - entry of the container
1448 */
1449 void VISU::Curve_i::removeContainer(const QString& id) {
1450   myContainers.insert(id);
1451 }
1452
1453 /*!
1454   Get all owners of the curve.
1455   \return owners of the curve.
1456 */
1457 VISU::ContainerSet VISU::Curve_i::getContainers() const {
1458   return myContainers;
1459 }
1460
1461 /*!
1462   Return true if on the curve were assigned deviation data
1463 */
1464 bool VISU::Curve_i::hasDeviation() {
1465   return myTable && myTable->hasDeviationData(myVRow-1);
1466 }
1467
1468 /*!
1469   Enable/disable deviation data displaying.
1470 */
1471 void  VISU::Curve_i::ShowDeviation(CORBA::Boolean flag) {
1472   if(flag && hasDeviation())
1473     myDeviationEnabled = flag;
1474   else
1475     myDeviationEnabled = false;
1476 }
1477 /*!
1478   Return enable deviation flag
1479 */
1480 bool VISU::Curve_i::isDeviationShown() {
1481   return myDeviationEnabled;
1482 }
1483
1484 //----------------------------------------------------------------
1485 //                      Container Object
1486 //----------------------------------------------------------------
1487 int VISU::Container_i::myNbPresent = 0;
1488 const string VISU::Container_i::myComment  = "CONTAINER";
1489 /*!
1490   Generate unique name
1491 */
1492 QString VISU::Container_i::GenerateName()
1493 {
1494   return VISU::GenerateName( "Plot2DView", ++myNbPresent ).toLatin1().data();
1495 }
1496 /*!
1497   Gets comment string
1498 */
1499 const char* VISU::Container_i::GetComment() const
1500 {
1501   return myComment.c_str();
1502 }
1503 /*!
1504   Constructor
1505 */
1506 VISU::Container_i::Container_i( SALOMEDS::Study_ptr theStudy )
1507      : PrsObject_i( theStudy )
1508 {
1509 }
1510 /*!
1511   Destructor
1512 */
1513 VISU::Container_i::~Container_i()
1514 {
1515   MESSAGE("Container_i::~Container_i");
1516   myCurves.clear();
1517 }
1518 /*!
1519   Inserts curve into the container
1520 */
1521 void VISU::Container_i::AddCurve( Curve_ptr theCurve )
1522 {
1523   if ( GetStudyDocument()->_is_nil() )
1524     return;
1525   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1526   if ( mySO->_is_nil() )
1527     return;
1528   PortableServer::POA_ptr aPOA = GetPOA();
1529   Curve_i* pCurve = dynamic_cast<Curve_i*>( aPOA->reference_to_servant( theCurve ) );
1530   if( pCurve ) {
1531     QString entry( pCurve->GetEntry().c_str() );
1532     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( entry.toLatin1().data() );
1533     if ( !SO->_is_nil() && myCurves.indexOf( entry ) == -1 ) {
1534       myCurves.append( entry );
1535       SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1536       SALOMEDS::SObject_var newSO = Builder->NewObject( mySO );
1537       Builder->Addreference( newSO, SO );
1538       pCurve->addContainer(GetEntry().c_str());
1539     }
1540   }
1541 }
1542 /*!
1543   Removes curve from the container
1544 */
1545 void VISU::Container_i::RemoveCurve( Curve_ptr theCurve )
1546 {
1547   if ( GetStudyDocument()->_is_nil() )
1548     return;
1549   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1550   if ( mySO->_is_nil() )
1551     return;
1552   PortableServer::POA_ptr aPOA = GetPOA();
1553   Curve_i* pCurve = dynamic_cast<Curve_i*>( aPOA->reference_to_servant( theCurve ) );
1554   if( pCurve ) {
1555     QString entry( pCurve->GetEntry().c_str() );
1556     if ( myCurves.indexOf( entry ) != -1 ) {
1557       // found !!!
1558       myCurves.removeAll( entry );
1559       SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1560       SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1561       for ( ; CI->More(); CI->Next() ) {
1562         SALOMEDS::SObject_var childSO = CI->Value();
1563         SALOMEDS::SObject_var refSO;
1564         if ( childSO->ReferencedObject( refSO ) && !refSO->_is_nil() && entry == QString( refSO->GetID() ) ) {
1565           Builder->RemoveObject( childSO );
1566         }
1567       }
1568       pCurve->removeContainer(GetEntry().c_str());
1569     }
1570   }
1571 }
1572 /*!
1573   Gets number of curves in the container
1574 */
1575 CORBA::Long VISU::Container_i::GetNbCurves()
1576 {
1577   //  Update();
1578   return myCurves.count();
1579 }
1580 /*!
1581   Clears container
1582 */
1583 void VISU::Container_i::Clear()
1584 {
1585   if ( GetStudyDocument()->_is_nil() )
1586     return;
1587   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1588   if ( mySO->_is_nil() )
1589     return;
1590   QStringList toDelete;
1591   SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1592   for ( ; CI->More(); CI->Next() ) {
1593     toDelete.append( CI->Value()->GetID() );
1594   }
1595   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1596   for ( int i = 0; i < toDelete.count(); i++ ) {
1597     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( toDelete[i].toLatin1().data() );
1598     Builder->RemoveObject( SO );
1599   }
1600   myCurves.clear();
1601 }
1602 /*!
1603   Creates container object
1604 */
1605 VISU::Storable* VISU::Container_i::Create()
1606 {
1607   // generate name ...
1608   SetName(GenerateName().toLatin1().data(), false);
1609   // ... and build the object
1610   return Build( false );
1611 }
1612 /*!
1613   Builds presentation of container
1614 */
1615 VISU::Storable* VISU::Container_i::Build( int theRestoring )
1616 {
1617   if ( !theRestoring ) {
1618     // looking for component
1619     SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
1620     // create SObject and set attributes
1621     QString aComment;
1622     aComment.sprintf("myComment=%s",GetComment());
1623     string anEntry = CreateAttributes( GetStudyDocument(),
1624                                        SComponent->GetID(),
1625                                        "",
1626                                        GetID(),
1627                                        GetName(),
1628                                        "",
1629                                        aComment.toLatin1().data(),
1630                                        true );
1631     mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID(anEntry.c_str()));
1632
1633     // Set icon
1634     SALOMEDS::StudyBuilder_var aStudyBuilder = GetStudyDocument()->NewBuilder();
1635     SALOMEDS::GenericAttribute_var anAttr;
1636     SALOMEDS::AttributePixMap_var  aPixmap;
1637     anAttr  = aStudyBuilder->FindOrCreateAttribute( mySObj, "AttributePixMap" );
1638     aPixmap = SALOMEDS::AttributePixMap::_narrow( anAttr );
1639     aPixmap ->SetPixMap("ICON_TREE_CONTAINER");
1640   }
1641   return this;
1642 }
1643 /*!
1644   Updates presentation of container
1645 */
1646 void VISU::Container_i::Update()
1647 {
1648   if ( GetStudyDocument()->_is_nil() )
1649     return;
1650   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1651   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1652   SALOMEDS::GenericAttribute_var anAttr;
1653   if ( !mySO->_is_nil() ) {
1654     QStringList toDelete;
1655     int i;
1656     for ( i = 0; i < myCurves.count(); i++ ) {
1657       SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( myCurves[i].toLatin1().data() );
1658       if ( !SO->_is_nil() && Builder->FindAttribute( SO, anAttr, "AttributeIOR" ) ) {
1659         // if real Curve Object still exists
1660         SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1661         bool bFound = false;
1662         for ( ; CI->More(); CI->Next() ) {
1663           SALOMEDS::SObject_var childSO = CI->Value();
1664           SALOMEDS::SObject_var refSO;
1665           if ( childSO->ReferencedObject( refSO ) && !refSO->_is_nil() && myCurves[i] == QString( refSO->GetID() ) ) {
1666             bFound = true; break;
1667           }
1668         }
1669         if (! bFound ) {
1670           // create SObject referenced to real curve object if is not yet added
1671           SALOMEDS::SObject_var newSO = Builder->NewObject( mySO );
1672           Builder->Addreference( newSO, SO );
1673         }
1674       }
1675       else {
1676         // real Curve Object doesn't exist (might be removed)
1677         toDelete.append( myCurves[i] );
1678       }
1679     }
1680     for ( i = 0; i < toDelete.count(); i++ ) {
1681       myCurves.removeAll( toDelete[i] );
1682     }
1683     toDelete.clear();
1684     SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1685     for ( ; CI->More(); CI->Next() ) {
1686       SALOMEDS::SObject_var childSO = CI->Value();
1687       SALOMEDS::SObject_var refSO;
1688       if ( childSO->ReferencedObject( refSO ) && ( refSO->_is_nil() || !Builder->FindAttribute( refSO, anAttr, "AttributeIOR" ) ||
1689                                                    myCurves.indexOf( refSO->GetID() ) == -1 ) ) {
1690         toDelete.append( childSO->GetID() );
1691       }
1692     }
1693     for ( i = 0; i < toDelete.count(); i++ ) {
1694       SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1695       for ( ; CI->More(); CI->Next() ) {
1696         SALOMEDS::SObject_var childSO = CI->Value();
1697         if ( toDelete[i] == CI->Value()->GetID() ) {
1698           Builder->RemoveObject( childSO );
1699         }
1700       }
1701     }
1702   }
1703 }
1704 /*!
1705   Gets curve from container by index
1706   NB : curves are numbered from 1
1707 */
1708 VISU::Curve_i* VISU::Container_i::GetCurve( CORBA::Long theIndex )
1709 {
1710   if ( theIndex > 0 && theIndex <= myCurves.count()  ) {
1711     SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1712     SALOMEDS::GenericAttribute_var anAttr;
1713     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myCurves[ theIndex-1 ].toLatin1().data() );
1714     CORBA::Object_var anObject = VISU::SObjectToObject( SO );
1715     if( !CORBA::is_nil( anObject ) ) {
1716       // if real Curve Object exists
1717       CORBA::Object_ptr aCurve = VISU::Curve::_narrow( anObject );
1718       if( !CORBA::is_nil( aCurve ) )
1719       return dynamic_cast<VISU::Curve_i*>(VISU::GetServant(aCurve).in());
1720     }
1721   }
1722   return NULL;
1723 }
1724 /*!
1725   Restores container data from the stream
1726 */
1727 VISU::Storable* VISU::Container_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr SO )
1728 {
1729   if(MYDEBUG) MESSAGE(GetComment());
1730   mySObj = SALOMEDS::SObject::_duplicate(SO);
1731   SetName(VISU::Storable::FindValue( theMap, "myName" ).toLatin1().data(), false);
1732   QString val = VISU::Storable::FindValue( theMap, "myCurves" );
1733   myCurves = val.split( "*", QString::SkipEmptyParts );
1734   return Build( true );
1735 }
1736 /*!
1737   Flushes container data into the stream
1738 */
1739 void VISU::Container_i::ToStream( std::ostringstream& theStr )
1740 {
1741   Storable::DataToStream( theStr, "myName",   GetName().c_str() );
1742   Storable::DataToStream( theStr, "myCurves", myCurves.join( QString( "*" ) ) );
1743 //  theStr<<" myName "<<myName;
1744 //  theStr<<" myCurves "<<myCurves.join( QString( "*" ) ).latin1()<<"* ";
1745 }
1746 /*!
1747   Called from engine to restore container from the file
1748 */
1749 VISU::Storable* VISU::Container_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
1750                                                   const Storable::TRestoringMap& theMap,
1751                                                   const std::string& thePrefix,
1752                                                   CORBA::Boolean theIsMultiFile)
1753 {
1754   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
1755   VISU::Container_i* pResent = new VISU::Container_i( aStudy );
1756   return pResent->Restore( theMap, theSObject );
1757 }
1758
1759 void VISU::Container_i::RemoveFromStudy()
1760 {
1761   struct TRemoveFromStudy: public SALOME_Event
1762   {
1763     VISU::Container_i* myRemovable;
1764     TRemoveFromStudy(VISU::Container_i* theRemovable):
1765       myRemovable(theRemovable)
1766     {}
1767     
1768     virtual
1769     void
1770     Execute()
1771     {
1772       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
1773     }
1774   };
1775
1776   ProcessVoidEvent(new TRemoveFromStudy(this));
1777 }
1778
1779 SALOMEDS::SObject_var VISU::Container_i::GetSObject()
1780 {
1781   return mySObj;
1782 }
1783
1784 SALOMEDS::SObject_var
1785 VISU::ImportTables(const char* theFileName, SALOMEDS::Study_ptr theStudy,
1786                    bool theFirstStrAsTitle)
1787 {
1788   // Set "C" numeric locale to import numbers correctly
1789   Kernel_Utils::Localizer loc;
1790
1791   TTableContainer aContainer;
1792   ImportTables( theFileName, aContainer, theFirstStrAsTitle );
1793   if ( aContainer.empty() ) 
1794     return SALOMEDS::SObject::_nil();
1795
1796   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
1797   SALOMEDS::SComponent_var theSComponent = VISU::FindOrCreateVisuComponent(theStudy);
1798   SALOMEDS::SObject_var aFileObject = aStudyBuilder->NewObject(theSComponent);
1799   SALOMEDS::GenericAttribute_var anAttr =
1800     aStudyBuilder->FindOrCreateAttribute(aFileObject, "AttributeName");
1801   SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
1802   QFileInfo aFileInfo(theFileName);
1803   aName->SetValue( aFileInfo.fileName().toLatin1().data());
1804   anAttr = aStudyBuilder->FindOrCreateAttribute(aFileObject, "AttributeString");
1805   SALOMEDS::AttributeString_var aComment = SALOMEDS::AttributeString::_narrow(anAttr);
1806   QString aString;
1807   aString.sprintf("myComment=ImportTables;myFileName=%s;myFirstStrAsTitle=%d",
1808                   aFileInfo.absoluteFilePath().toLatin1().data(),theFirstStrAsTitle);
1809   aComment->SetValue(aString.toLatin1().data());
1810   for(int i = 0, iEnd = aContainer.size(); i < iEnd; i++) {
1811     PTableIDMapper aTableIDMapper = aContainer[i];
1812     const TTable2D& aTable2D = *aTableIDMapper;
1813     SALOMEDS::SObject_var aRealObject = aStudyBuilder->NewObject(aFileObject);
1814     anAttr = aStudyBuilder->FindOrCreateAttribute(aRealObject, "AttributeName");
1815     aName = SALOMEDS::AttributeName::_narrow(anAttr);
1816     if(MYDEBUG) MESSAGE("aTable2D.myTitle = "<<aTable2D.myTitle);
1817     if ( aTable2D.myTitle != "" ) {
1818       aName->SetValue(aTable2D.myTitle.c_str());
1819     }
1820     else {
1821       QString aNewName;
1822       aNewName.sprintf("Table:%d",i);
1823       aName->SetValue(aNewName.toLatin1().data());
1824     }
1825
1826     anAttr = aStudyBuilder->FindOrCreateAttribute(aRealObject, "AttributeTableOfReal");
1827     SALOMEDS::AttributeTableOfReal_var aTableOfReal = SALOMEDS::AttributeTableOfReal::_narrow(anAttr);
1828     aTableOfReal->SetTitle(aTable2D.myTitle.c_str());
1829     TTable2D aNewTable2D;
1830     aTable2D.getColumns(aNewTable2D);
1831     int kEnd = aNewTable2D.myRows[0].myValues.size();
1832     // check empty columns
1833     TColStd_MapOfInteger EmptyColumns;
1834     for(int j = 0, jEnd = aNewTable2D.myRows.size(); j < jEnd; j++) {
1835       bool hasVal = false;
1836       for(int k = 0; k < kEnd; k++) {
1837         QString aVal = aNewTable2D.myRows[j].myValues[k].c_str();
1838         bool anIsOk = false;
1839         double aValue = aVal.toDouble(&anIsOk);
1840         if(anIsOk) {
1841           hasVal = true;
1842           break;
1843         }
1844       }
1845       if(!hasVal) {
1846         EmptyColumns.Add(j);
1847       }
1848     }
1849     // create table of real
1850     aTableOfReal->SetNbColumns( kEnd - EmptyColumns.Extent() );
1851     int currNum = -1;
1852     for(int j = 0, jEnd = aNewTable2D.myRows.size(); j < jEnd; j++) {
1853       if( EmptyColumns.Contains(j) ) continue;
1854       currNum++;
1855       if(MYDEBUG) MESSAGE("j = "<<j<<"; kEnd = "<<kEnd);
1856       for(int k = 0; k < kEnd; k++) {
1857         QString aVal = aNewTable2D.myRows[j].myValues[k].c_str();
1858         bool anIsOk = false;
1859         double aValue = aVal.toDouble(&anIsOk);
1860         if( anIsOk && !aVal.contains("NAN",Qt::CaseInsensitive) &&
1861             !aVal.contains("INF",Qt::CaseInsensitive) ) {
1862           aTableOfReal->PutValue(aValue,currNum+1,k+1);
1863         }
1864       }
1865       aTableOfReal->SetRowTitle(currNum+1,aNewTable2D.myRows[j].myTitle.c_str());
1866       aTableOfReal->SetRowUnit(currNum+1,aNewTable2D.myRows[j].myUnit.c_str());
1867     }
1868     for(int k = 0; k < kEnd; k++)
1869       aTableOfReal->SetColumnTitle(k+1,aNewTable2D.myColumnTitles[k].c_str());
1870   }
1871   return aFileObject;
1872 }
1873
1874
1875 //=======================================================================
1876 //function : updateStrForCSV
1877 //purpose  : auxilary for ExportTableToFile
1878 //=======================================================================
1879 void updateStrForCSV(QString& aStr, const char aSep)
1880 {
1881   int index = aStr.indexOf('"');
1882   while(index>=0) {
1883     aStr.insert(index,'"');
1884     if( index+2 >= aStr.size() ) break;
1885     index = aStr.indexOf('"',index+2);
1886   }
1887   index = aStr.indexOf(aSep);
1888   if(index>=0) {
1889     // current string contains separator => need to use "..."
1890     aStr.insert(0,'"');
1891     aStr.push_back('"');
1892   }
1893 }
1894
1895
1896 //=======================================================================
1897 //function : ExportTableToFile
1898 //purpose  : 
1899 //=======================================================================
1900 template<class TTableAttr> bool ExportTableToFile(const TTableAttr& aTabAttr,
1901                                                   const char* theFileName)
1902 {
1903   if (CORBA::is_nil(aTabAttr))
1904     return false;
1905
1906   // Set "C" numeric locale to save numbers correctly
1907   Kernel_Utils::Localizer loc;
1908
1909   QFile aFile(theFileName);
1910   aFile.open(QIODevice::WriteOnly);
1911
1912   /* extract the table info and write it into file */
1913
1914   QString aTitle(aTabAttr->GetTitle()); /*Table title*/
1915   int aRowsNb = aTabAttr->GetNbRows();
1916   int aColNb  = aTabAttr->GetNbColumns();
1917
1918   SALOMEDS::StringSeq_var aRowTitles = aTabAttr->GetRowTitles();
1919   SALOMEDS::StringSeq_var aRowUnits = aTabAttr->GetRowUnits();
1920   SALOMEDS::StringSeq_var aColumnTitles = aTabAttr->GetColumnTitles();
1921
1922   //--------------------------------------------------
1923   //    write as *.csv file if it is needed
1924   //--------------------------------------------------
1925   QString tmp(theFileName);
1926   tmp = tmp.trimmed();
1927   tmp = tmp.right(3).trimmed();
1928   if( tmp == QString("csv") ) {
1929     const char aSep = ',';
1930     // write column titles
1931     QString aLine(aRowTitles[0]);
1932     updateStrForCSV(aLine,aSep);
1933     for(int i=1; i<aRowsNb; i++) {
1934       aLine += aSep;
1935       QString aTmp(aRowTitles[i]);
1936       updateStrForCSV(aTmp,aSep);
1937       aLine += aTmp;
1938     }
1939     aLine += "\n";
1940     aFile.write(aLine.toLatin1() );
1941     // write table data
1942     QString aValue;
1943     for (int j = 1; j <= aColNb; j++) {
1944       QString aLine = "";
1945       if(aTabAttr->HasValue(1,j)) {
1946         aLine = aValue.sprintf("%.16g",(double)aTabAttr->GetValue(1,j));
1947       }
1948       for (int i = 2; i <= aRowsNb; i++) {
1949         if(aTabAttr->HasValue(i,j)) {
1950           aLine += aSep + aValue.sprintf("%.16g",(double)aTabAttr->GetValue(i,j));
1951         }
1952         else aLine += aSep;
1953       }
1954       aLine += "\n";
1955       aFile.write(aLine.toLatin1() );
1956     }
1957
1958     aFile.close();
1959     return true;
1960   }
1961   //--------------------------------------------------
1962   //       end of writing as *.csv file
1963   //--------------------------------------------------
1964
1965   /* The given table is rare (some cells is empty) or not? */
1966   bool isRareTable = false;
1967   for (int i = 1; i <= aRowsNb; i++)
1968     for (int j = 1; j <= aColNb && !isRareTable; j++)
1969       isRareTable = !aTabAttr->HasValue(i,j);
1970
1971   QString aLine;
1972   if (isRareTable) {
1973     /* Separate the given table to 2D tables and write these ones to the file */
1974     QString anAbscissTitle(aRowTitles[0]); /*Absciss row title (X coord)*/
1975     anAbscissTitle.trimmed();
1976     QString anAbscissUnit(aRowUnits[0]);
1977     anAbscissUnit.trimmed();
1978     if (aRowsNb > 2 && aTitle.length() )  aTitle = aTitle + " - ";
1979
1980     for (int i = 2; i <= aRowsNb; i++ )
1981       {
1982         /* TITLE */
1983         QString anOrdinate(aRowTitles[i-1]), aTail;
1984         anOrdinate.trimmed();
1985
1986         aLine = "#TITLE: " + aTitle +
1987           ((anOrdinate.length())?  anOrdinate :
1988                                   (aRowsNb>2)? aTail.sprintf("%d",i-1) : aTail.sprintf("") ) + "\n";
1989         aFile.write(aLine.toLatin1() );
1990
1991         /* COLUMN_TITLES */
1992         if ( anAbscissTitle.length() || anOrdinate.length() ) {
1993           aLine = "#COLUMN_TITLES: " + anAbscissTitle + " | " + anOrdinate;
1994           int tmpind = aLine.indexOf("\n");
1995           while(tmpind>=0) {
1996             aLine.remove(tmpind,1);
1997             tmpind = aLine.indexOf("\n");
1998           }
1999           aLine += "\n";
2000           aFile.write(aLine.toLatin1() );
2001         }
2002
2003         /* COLUMN_UNITS */
2004         aLine = anAbscissUnit + " " +aRowUnits[i-1];
2005         if (!aLine.trimmed().isEmpty()) {
2006           aLine = "#COLUMN_UNITS: " + aLine  + "\n";
2007           aFile.write(aLine.toLatin1() );
2008         }
2009
2010         /* CURVE COORDINATES */
2011         for (int j = 1; j <= aColNb; j++)
2012           {
2013             if ( aTabAttr -> HasValue(i,j) &&  aTabAttr -> HasValue(1, j)) {
2014               aLine = aLine.sprintf("%.16g %.16g",
2015                                     (double)(aTabAttr->GetValue(1,j)),
2016                                     (double)(aTabAttr->GetValue(i,j)));  /* aTabAttr->GetValue(1,j) - X coord */
2017               if ( !aLine.trimmed().isEmpty() ) {
2018                 QString aColTitle(aColumnTitles[j-1]);
2019                 if ( !aColTitle.trimmed().isEmpty() )
2020                   aLine = aLine + "  #TITLE: " + aColTitle ;
2021                 aFile.write(QString(aLine + "\n").toLatin1() );
2022               }
2023             }
2024           }
2025         aFile.write("\n", 1);
2026       }
2027   }//end of if (isRareTable)
2028   else {
2029     /* Write the table in the file without separating */
2030     /* TITLE */
2031     aLine = "#TITLE: " + aTitle + "\n";
2032     aFile.write(aLine.toLatin1());
2033
2034     /* COLUMN_TITLES  and COLUMN_UNITS */
2035     QString aTitlesSep = "";
2036     QString aUnitsSep  = "";
2037     QString aTitlesStr = "#COLUMN_TITLES: ";
2038     QString aUnitsStr  = "#COLUMN_UNITS: ";
2039     for (int i = 1; i <= aRowsNb; i++) {
2040       if (!QString(aRowTitles[i-1]).trimmed().isEmpty()) {
2041         aTitlesStr += (aTitlesSep + aRowTitles[i-1]);
2042         if (aTitlesSep.isEmpty()) aTitlesSep = " | ";
2043       }
2044       if (!QString(aRowUnits[i-1]).trimmed().isEmpty()) {
2045         aUnitsStr += (aUnitsSep + aRowUnits[i-1]);
2046         if (aUnitsSep.isEmpty()) aUnitsSep = " ";
2047       }
2048     }
2049     int tmpind = aTitlesStr.indexOf("\n");
2050     while(tmpind>=0) {
2051       aTitlesStr.remove(tmpind,1);
2052       tmpind = aTitlesStr.indexOf("\n");
2053     }
2054     aTitlesStr += "\n";
2055     aUnitsStr  += "\n";
2056     aFile.write(aTitlesStr.toLatin1());
2057     aFile.write(aUnitsStr.toLatin1());
2058
2059     /* CURVE COORDINATES */
2060     QString aSep, aValue, aColTitle;
2061     for (int j = 1; j <= aColNb; j++) {
2062       aLine = ""; aSep  = "";
2063       for (int i = 1; i <= aRowsNb; i++) {
2064         aLine += (aSep + aValue.sprintf("%.16g", (double)(aTabAttr->GetValue(i,j))));
2065         if (aSep.isEmpty()) aSep = " ";
2066       }
2067       if (!aLine.trimmed().isEmpty()) {
2068         aColTitle = aColumnTitles[j-1];
2069         if (!aColTitle.trimmed().isEmpty())
2070           aLine = aLine + "  #TITLE: " + aColTitle;
2071         aLine += "\n";
2072         aFile.write(aLine.toLatin1());
2073       }
2074     }
2075   } //end of else
2076
2077   aFile.close();
2078   return true;
2079 }
2080
2081 bool VISU::ExportTableToFile(SALOMEDS::SObject_ptr theTable, const char* theFileName)
2082 {
2083   //Find table
2084   SALOMEDS::GenericAttribute_var anAttr ;
2085   if (theTable->FindAttribute(anAttr, "AttributeTableOfReal")) {
2086     SALOMEDS::AttributeTableOfReal_var aTabAttr =
2087       SALOMEDS::AttributeTableOfReal ::_narrow(anAttr);
2088     return ExportTableToFile ( aTabAttr , theFileName);
2089   }
2090   else if (theTable->FindAttribute(anAttr, "AttributeTableOfInteger")) {
2091     SALOMEDS::AttributeTableOfInteger_var aTabAttr =
2092       SALOMEDS::AttributeTableOfInteger ::_narrow(anAttr);
2093     return ExportTableToFile ( aTabAttr , theFileName);
2094   }
2095   return false;
2096 }