Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/visu.git] / src / VISU_I / VISU_Table_i.cc
1 // Copyright (C) 2007-2012  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   return Build( true );
684 }
685 /*!
686   Flushes table data into stream
687 */
688 void VISU::Table_i::ToStream( std::ostringstream& theStr )
689 {
690   Storable::DataToStream( theStr, "myName",        GetName().c_str() );
691   Storable::DataToStream( theStr, "myTitle",       myTitle.c_str() );
692   Storable::DataToStream( theStr, "myOrientation", myOrientation );
693 }
694 /*!
695   Called from engine to restore table from the file
696 */
697 VISU::Storable* VISU::Table_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
698                                               const Storable::TRestoringMap& theMap,
699                                               const std::string& thePrefix,
700                                               CORBA::Boolean theIsMultiFile)
701 {
702   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
703   VISU::Table_i* pResent = new VISU::Table_i( aStudy, "" );
704   return pResent->Restore( theMap, theSObject);
705 }
706 /*!
707   Gets title for the original table object
708 */
709 QString VISU::Table_i::GetTableTitle()
710 {
711   SALOMEDS::SObject_var SO = mySObj;
712   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
713   SALOMEDS::GenericAttribute_var        anAttr;
714   SALOMEDS::AttributeTableOfInteger_var anInt;
715   SALOMEDS::AttributeTableOfReal_var    aReal;
716   if ( !SO->_is_nil() ) {
717     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
718       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
719       CORBA::String_var aString = anInt->GetTitle();
720       return aString.in();
721     }
722     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
723       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
724       CORBA::String_var aString = aReal->GetTitle();
725       return aString.in();
726     }
727   }
728   return "";
729 }
730
731 //---------------------------------------------------------------
732 void VISU::Table_i::RemoveFromStudy()
733 {
734   struct TRemoveFromStudy: public SALOME_Event
735   {
736     VISU::Table_i* myRemovable;
737     TRemoveFromStudy(VISU::Table_i* theRemovable):
738       myRemovable(theRemovable)
739     {}
740     
741     virtual
742     void
743     Execute()
744     {
745       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
746     }
747   };
748
749   // Remove the table with all curves
750   ProcessVoidEvent(new TRemoveFromStudy(this));
751 }
752
753 //----------------------------------------------------------------
754 //                      Curve Object
755 //----------------------------------------------------------------
756 /*!
757   Restores table object from the stream [ static ]
758 */
759 static VISU::Table_i* GetTable( SALOMEDS::Study_ptr theStudy, SALOMEDS::SObject_ptr theSO ) {
760   CORBA::Object_var anObject = VISU::SObjectToObject( theSO );
761   if( !CORBA::is_nil( anObject ) ) {
762     CORBA::Object_ptr aTable = VISU::Table::_narrow( anObject );
763     if( !CORBA::is_nil( aTable ) )
764       return dynamic_cast<VISU::Table_i*>(VISU::GetServant(aTable).in());
765   }
766   return NULL;
767 }
768
769 int VISU::Curve_i::myNbPresent = 0;
770 const string VISU::Curve_i::myComment  = "CURVE";
771 /*!
772   Generate unique name
773 */
774 QString VISU::Curve_i::GenerateName()
775 {
776   return VISU::GenerateName( "Curve", ++myNbPresent ).toLatin1().data();
777 }
778 /*!
779   Gets comment string
780 */
781 const char* VISU::Curve_i::GetComment() const
782 {
783   return myComment.c_str();
784 }
785 /*!
786   Constructor
787   NB : theHRow, theVRow are the indexes of rows in the Table object and numbered from the 1 to GetNbRows()
788 */
789 VISU::Curve_i::Curve_i( SALOMEDS::Study_ptr theStudy, Table_i* theTable,
790                         CORBA::Long theHRow, CORBA::Long theVRow,
791                         CORBA::Long theZRow, CORBA::Boolean theIsV2 )
792 : PrsObject_i(theStudy), myTable( theTable ), myHRow( theHRow ),
793   myVRow( theVRow ), myZRow( theZRow ), myIsV2( theIsV2 ), myDeviationEnabled(false)
794 {
795   myAuto = true;
796   myLine = VISU::Curve::SOLIDLINE;
797   myLineWidth = 0;
798   myMarker = VISU::Curve::CIRCLE;
799   myColor.R = 0.0; myColor.G = 0.0; myColor.B = 0.0;
800   myScale = 1.0;
801 }
802 /*!
803   Destructor
804 */
805 VISU::Curve_i::~Curve_i()
806 {
807   MESSAGE("Curve_i::~Curve_i");
808 }
809
810 //----------------------------------------------------------------------------
811 void
812 VISU::Curve_i
813 ::SetTitle( const char* theTitle )
814 {
815   SetName( theTitle, true );
816 }
817
818 //----------------------------------------------------------------------------
819 char*
820 VISU::Curve_i
821 ::GetTitle()
822 {
823   return CORBA::string_dup( GetName().c_str() );
824 }
825
826 //----------------------------------------------------------------------------
827 void
828 VISU::Curve_i
829 ::SetColor( const SALOMEDS::Color& theColor )
830 {
831   myColor = theColor; 
832   myAuto = false;
833 }
834
835 //----------------------------------------------------------------------------
836 SALOMEDS::Color
837 VISU::Curve_i
838 ::GetColor()
839 {
840   return myColor;
841 }
842
843 //----------------------------------------------------------------------------
844 void
845 VISU::Curve_i
846 ::SetMarker( VISU::Curve::MarkerType theType )
847 {
848   myMarker = theType; 
849   myAuto = false;
850 }
851
852 //----------------------------------------------------------------------------
853 VISU::Curve::MarkerType
854 VISU::Curve_i
855 ::GetMarker()
856 {
857   return myMarker;
858 }
859
860 //----------------------------------------------------------------------------
861 void
862 VISU::Curve_i
863 ::SetLine( VISU::Curve::LineType theType, CORBA::Long theWidth )
864 {
865   myLine = theType; 
866   myLineWidth = theWidth; 
867   myAuto = false;
868 }
869
870 //----------------------------------------------------------------------------
871 VISU::Curve::LineType
872 VISU::Curve_i
873 ::GetLine()
874 {
875   return myLine;
876 }
877
878 //----------------------------------------------------------------------------
879 CORBA::Long
880 VISU::Curve_i
881 ::GetLineWidth()
882 {
883   return myLineWidth;
884 }
885
886 //----------------------------------------------------------------------------
887 void 
888 VISU::Curve_i
889 ::SetScale( CORBA::Double theCoef )
890 {
891   myScale = theCoef;  
892   UpdatePlot2d( this, eUpdateData );
893 }
894
895 //----------------------------------------------------------------------------
896 CORBA::Double 
897 VISU::Curve_i
898 ::GetScale()
899 {
900   return myScale;    
901 }
902
903 //----------------------------------------------------------------------------
904 void 
905 VISU::Curve_i
906 ::RemoveScale()
907 {
908   SetScale( 1.0 );
909 }
910
911 //----------------------------------------------------------------------------
912 /*!
913   Creates curve object
914 */
915 VISU::Storable* VISU::Curve_i::Create()
916 {
917   // generate name ...
918   SetName(GetVerTitle(), false);
919   if ( GetName() == "" )
920     SetName(GenerateName().toLatin1().data(), false);
921   // ... and build the object
922   return Build( false );
923 }
924 /*!
925   Builds presentation of curve
926 */
927 VISU::Storable* VISU::Curve_i::Build(int theRestoring )
928 {
929   if ( myTable != NULL ) {
930     // getting table SObject by it's entry
931     int nbRows = myTable->GetNbRows();
932     if ( myHRow > 0 && myHRow <= nbRows && myVRow > 0 && myVRow <= nbRows ) {
933       if ( !theRestoring ) {
934         // look for component
935         SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
936         // create SObject and set attributes
937         QString aComment;
938         aComment.sprintf("myComment=%s",GetComment());
939         string anEntry = CreateAttributes( GetStudyDocument(),
940                                           myTable->GetObjectEntry(),
941                                           "",
942                                           GetID(),
943                                           GetName(),
944                                           "",
945                                           aComment.toLatin1().data(),
946                                           true );
947         // create SObject referenced to real table object
948         mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID(anEntry.c_str()));
949
950         // Set icon
951         SALOMEDS::StudyBuilder_var aStudyBuilder = GetStudyDocument()->NewBuilder();
952         SALOMEDS::GenericAttribute_var anAttr;
953         SALOMEDS::AttributePixMap_var  aPixmap;
954         anAttr  = aStudyBuilder->FindOrCreateAttribute( mySObj, "AttributePixMap" );
955         aPixmap = SALOMEDS::AttributePixMap::_narrow( anAttr );
956         aPixmap ->SetPixMap("ICON_TREE_CURVE");
957       }
958       return this;
959     }
960   }
961   return NULL;
962 }
963
964 /*!
965   Returns CORBA::True if curve refers to valid table data
966 */
967 CORBA::Boolean VISU::Curve_i::IsValid()
968 {
969   // getting table SObject by it's entry
970   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
971   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
972   SALOMEDS::GenericAttribute_var        anAttr;
973   SALOMEDS::AttributeTableOfInteger_var anInt;
974   SALOMEDS::AttributeTableOfReal_var    aReal;
975   if ( !SO->_is_nil() ) {
976     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
977       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
978       if ( myHRow > 0 && myHRow <= anInt->GetNbRows() && myVRow > 0 && myVRow <= anInt->GetNbRows() ) {
979         return true;
980       }
981     }
982     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
983       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
984       if ( myHRow > 0 && myHRow <= aReal->GetNbRows() && myVRow > 0 && myVRow <= aReal->GetNbRows() ) {
985         return true;
986       }
987     }
988   }
989   return false;
990 }
991 /*!
992   Returns hor.axis title
993 */
994 string VISU::Curve_i::GetHorTitle()
995 {
996   string title;
997   // getting table SObject by it's entry
998   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
999   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1000   SALOMEDS::GenericAttribute_var        anAttr;
1001   SALOMEDS::AttributeTableOfInteger_var anInt;
1002   SALOMEDS::AttributeTableOfReal_var    aReal;
1003   if ( !SO->_is_nil() ) {
1004     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1005       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1006       SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
1007       if ( rowTitles->length() > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() ) {
1008         title = rowTitles[ myHRow-1 ];
1009       }
1010     }
1011     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1012       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1013       SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
1014       if ( rowTitles->length() > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() ) {
1015         title = rowTitles[ myHRow-1 ];
1016       }
1017     }
1018   }
1019   return title;
1020 }
1021 /*!
1022   Returns ver.axis title
1023 */
1024 string VISU::Curve_i::GetVerTitle()
1025 {
1026   string title;
1027   // getting table SObject by it's entry
1028   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1029   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1030   SALOMEDS::GenericAttribute_var        anAttr;
1031   SALOMEDS::AttributeTableOfInteger_var anInt;
1032   SALOMEDS::AttributeTableOfReal_var    aReal;
1033   if ( !SO->_is_nil() ) {
1034     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1035       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1036       SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
1037       if ( rowTitles->length() > 0 && myVRow > 0 && myVRow <= anInt->GetNbRows() )
1038         title = rowTitles[ myVRow-1 ];
1039     }
1040     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1041       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1042       SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
1043       if ( rowTitles->length() > 0 && myVRow > 0 && myVRow <= aReal->GetNbRows() )
1044         title = rowTitles[ myVRow-1 ];
1045     }
1046   }
1047   return title;
1048 }
1049 /*!
1050   Returns hor.axis units
1051 */
1052 string VISU::Curve_i::GetHorUnits()
1053 {
1054   string units;
1055   // getting table SObject by it's entry
1056   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1057   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1058   SALOMEDS::GenericAttribute_var        anAttr;
1059   SALOMEDS::AttributeTableOfInteger_var anInt;
1060   SALOMEDS::AttributeTableOfReal_var    aReal;
1061   if ( !SO->_is_nil()  ) {
1062     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1063       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1064       SALOMEDS::StringSeq_var rowUnits = anInt->GetRowUnits();
1065       if ( rowUnits->length() > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() )
1066         units = rowUnits[ myHRow-1 ];
1067     }
1068     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1069       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1070       SALOMEDS::StringSeq_var rowUnits = aReal->GetRowUnits();
1071       if ( rowUnits->length() > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() )
1072         units = rowUnits[ myHRow-1 ];
1073     }
1074   }
1075   return units;
1076 }
1077 /*!
1078   Returns ver.axis units
1079 */
1080 string VISU::Curve_i::GetVerUnits()
1081 {
1082   string units;
1083   // getting table SObject by it's entry
1084   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1085   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1086   SALOMEDS::GenericAttribute_var        anAttr;
1087   SALOMEDS::AttributeTableOfInteger_var anInt;
1088   SALOMEDS::AttributeTableOfReal_var    aReal;
1089   if ( !SO->_is_nil() ) {
1090     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1091       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1092       SALOMEDS::StringSeq_var rowUnits = anInt->GetRowUnits();
1093       if ( rowUnits->length() > 0 && myVRow > 0 && myVRow <= anInt->GetNbRows() )
1094         units = rowUnits[ myVRow-1];
1095     }
1096     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1097       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1098       SALOMEDS::StringSeq_var rowUnits = aReal->GetRowUnits();
1099       if ( rowUnits->length() > 0 && myVRow > 0 && myVRow <= aReal->GetNbRows() )
1100         units = rowUnits[ myVRow-1 ];
1101     }
1102   }
1103   return units;
1104 }
1105 /*!
1106   Gets curve data
1107 */
1108 int VISU::Curve_i::GetData( double*& theHorList, double*& theVerList, QStringList& zList )
1109 {
1110   theHorList = 0; theVerList = 0;
1111   // getting table SObject by it's entry
1112   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1113   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1114   SALOMEDS::GenericAttribute_var        anAttr;
1115   SALOMEDS::AttributeTableOfInteger_var anInt;
1116   SALOMEDS::AttributeTableOfReal_var    aReal;
1117
1118   QString tip = "%1: %2", z_data;
1119
1120   if ( !SO->_is_nil() ) {
1121     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1122       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1123       int nbCols = anInt->GetNbColumns(), nbRows = anInt->GetNbRows();
1124       if ( nbCols > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() && myVRow > 0 && myVRow <= anInt->GetNbRows() ) {
1125         int nbPoints = 0;
1126         for ( int j = 1; j <= nbCols; j++ ) {
1127           if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) )
1128             nbPoints++;
1129         }
1130         if ( nbPoints > 0 ) {
1131           theHorList = new double[ nbPoints ];
1132           theVerList = new double[ nbPoints ];
1133           int k = 0;
1134
1135           SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
1136
1137           for ( int j = 1; j <= nbCols; j++ ) {
1138             if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) ) {
1139               theHorList[k] = anInt->GetValue( myHRow, j );
1140               theVerList[k] = anInt->GetValue( myVRow, j );
1141
1142               z_data = tip.arg( GetHorTitle().c_str() ).arg( theHorList[k] ) + "\n";
1143               z_data += tip.arg( GetVerTitle().c_str() ).arg( theVerList[k] );
1144
1145               if( myZRow>0 && myZRow<=nbRows && anInt->HasValue( myZRow, j ) )
1146               {
1147                 string title;
1148                 title = rowTitles[ myZRow-1 ];
1149                 z_data += "\n" + tip.arg( title.c_str() ).arg( anInt->GetValue( myZRow, j ) );
1150               }
1151               zList.append( z_data );
1152               k++;
1153             }
1154           }
1155         }
1156         return nbPoints;
1157       }
1158     }
1159     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1160       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1161       int nbCols = aReal->GetNbColumns(), nbRows = aReal->GetNbRows();
1162       if ( nbCols > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() && myVRow > 0 && myVRow <= aReal->GetNbRows() ) {
1163         int nbPoints = 0;
1164         for ( int j = 1; j <= nbCols; j++ ) {
1165           if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) )
1166             nbPoints++;
1167         }
1168         if ( nbPoints > 0 ) {
1169           theHorList = new double[ nbPoints ];
1170           theVerList = new double[ nbPoints ];
1171           int k = 0;
1172
1173           SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
1174
1175           for ( int j = 1; j <= nbCols; j++ ) {
1176             if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) ) {
1177               theHorList[k] = aReal->GetValue( myHRow, j );
1178               theVerList[k] = aReal->GetValue( myVRow, j );
1179
1180               z_data = tip.arg( GetHorTitle().c_str() ).arg( theHorList[k] ) + "\n";
1181               z_data += tip.arg( GetVerTitle().c_str() ).arg( theVerList[k] );
1182
1183               if( myZRow>0 && myZRow<=nbRows && aReal->HasValue( myZRow, j ) )
1184               {
1185                 string title;
1186                 title = rowTitles[ myZRow-1 ];
1187                 z_data += "\n" + tip.arg( title.c_str() ).arg( aReal->GetValue( myZRow, j ) );
1188               }
1189               zList.append( z_data );
1190               k++;
1191             }
1192           }
1193         }
1194         return nbPoints;
1195       }
1196     }
1197   }
1198   return 0;
1199 }
1200
1201 int VISU::Curve_i::GetDeviationData( double*& theMin, double*& theMax, QList<int>& theIndexes) {
1202   if(!hasDeviation())
1203     return 0;
1204
1205   theIndexes.clear();
1206
1207   DeviationData *info = myTable->getDeviationInfo(myVRow - 1);
1208   int minRow = info->minRow() + 1;
1209   int maxRow = info->maxRow() + 1;
1210
1211   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
1212   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1213   SALOMEDS::GenericAttribute_var        anAttr;
1214   SALOMEDS::AttributeTableOfInteger_var anInt;
1215   SALOMEDS::AttributeTableOfReal_var    aReal;
1216
1217   int nbPoints = 0;
1218   if ( !SO->_is_nil() ) {
1219     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
1220       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
1221       int nbCols = anInt->GetNbColumns();
1222       int nbRows = anInt->GetNbRows();
1223       if ( nbCols > 0 && myHRow > 0 && myVRow && minRow > 0 && maxRow > 0 && 
1224            myHRow <= nbRows &&  myVRow <= nbRows && minRow <= nbRows && maxRow <= nbRows ) {
1225         for ( int j = 1; j <= nbCols; j++ ) {
1226                 if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) && 
1227                anInt->HasValue( minRow, j ) && anInt->HasValue( maxRow, j ) )
1228                   nbPoints++;
1229         }
1230
1231           if ( nbPoints > 0 ) {
1232                 theMin = new double[ nbPoints ];
1233                 theMax = new double[ nbPoints ];
1234             int k = 0;
1235           int value;
1236                 for ( int j = 1; j <= nbCols; j++ ) {
1237                   if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) &&
1238                  anInt->HasValue( minRow, j ) && anInt->HasValue( maxRow, j )) {
1239                  value = anInt->GetValue(myVRow,j);
1240               theMin[k] = Table_i::calculateDeviation(info->minDeviation(),value, anInt->GetValue(minRow,j), true);
1241                     theMax[k] = Table_i::calculateDeviation(info->maxDeviation(),value, anInt->GetValue(maxRow,j), false);
1242               k++;
1243               theIndexes.push_back(j-1);
1244             }
1245           } // for ( ...
1246         } // nbPoints > 0
1247       } // nbCols > 0 && myHRow > 0 && myVRow ...
1248     } // Builder->FindAttribute(...
1249     else if( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
1250       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
1251       int nbCols = aReal->GetNbColumns();
1252       int nbRows = aReal->GetNbRows();
1253       if ( nbCols > 0 && myHRow > 0 && myVRow && minRow > 0 && maxRow > 0 && 
1254            myHRow <= nbRows &&  myVRow <= nbRows && minRow <= nbRows && maxRow <= nbRows) {
1255         for ( int j = 1; j <= nbCols; j++ ) {
1256                 if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) && 
1257                aReal->HasValue( minRow, j ) && aReal->HasValue( maxRow, j ) )
1258                   nbPoints++;
1259         }
1260
1261           if ( nbPoints > 0 ) {
1262                 theMin = new double[ nbPoints ];
1263                 theMax = new double[ nbPoints ];
1264             int k = 0;
1265           double value;
1266                 for ( int j = 1; j <= nbCols; j++ ) {
1267                   if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) &&
1268                  aReal->HasValue( minRow, j ) && aReal->HasValue( maxRow, j )) {
1269               value =  aReal->GetValue(myVRow,j);
1270               theMin[k] = Table_i::calculateDeviation(info->minDeviation(),value, aReal->GetValue(minRow,j), true);
1271               theMax[k] = Table_i::calculateDeviation(info->maxDeviation(),value, aReal->GetValue(maxRow,j), false);
1272               k++;
1273               theIndexes.push_back(j-1);
1274             }
1275           } // for ( ..
1276         } // nbPoints > 0
1277       } // nbCols > 0 && myHRow > 0 && myVRow ...
1278     } // Builder->FindAttribute( ...
1279   } // !SO->_is_nil()
1280   return nbPoints;
1281 }
1282 /*!
1283   Creates curve Plot2d presentation object
1284 */
1285 SPlot2d_Curve* VISU::Curve_i::CreatePresentation()
1286 {
1287   SPlot2d_Curve* crv = new SPlot2d_Curve();
1288   crv->setYAxis( myIsV2 ? QwtPlot::yRight : QwtPlot::yLeft );
1289   crv->setHorTitle( GetHorTitle().c_str() );
1290   string tlt = GetTitle();
1291   if ( tlt.length() <= 0 )
1292     tlt = GetVerTitle();
1293   //crv->setVerTitle( strdup( GetVerTitle().c_str() ) );
1294   //crv->setVerTitle( strdup( GetName() ) );
1295   crv->setVerTitle( tlt.c_str() );
1296   crv->setHorUnits( GetHorUnits().c_str() );
1297   crv->setVerUnits( GetVerUnits().c_str() );
1298   double* xList = 0;
1299   double* yList = 0;
1300   QStringList zList;
1301   int     nbPoints = GetData( xList, yList, zList );
1302   if ( nbPoints > 0 && xList && yList ) {
1303     crv->setData( xList, yList, nbPoints, zList );
1304   }
1305   //cout << "********** Number of points: " << nbPoints <<endl;
1306   //for ( int i =0 ; i < nbPoints; i++ ) {
1307   //  cout << i<<"\t"<<xList[i] << "\t"<< yList[i] << endl;
1308   //}
1309   crv->setLine( (Plot2d::LineType)GetLine(), GetLineWidth() );
1310   crv->setMarker( (Plot2d::MarkerType)GetMarker() );
1311   SALOMEDS::Color color = GetColor();
1312   crv->setColor( QColor( (int)(color.R*255.), (int)(color.G*255.), (int)(color.B*255.) ) );
1313   crv->setAutoAssign( IsAuto() );
1314   CORBA::String_var aString = mySObj->GetID();
1315   crv->setIO(new SALOME_InteractiveObject(aString.in(), "VISU", GetName().c_str()));
1316   if ( myTable )
1317     crv->setTableIO(new SALOME_InteractiveObject(myTable->GetObjectEntry().c_str(), "VISU", myTable->GetName().c_str()));
1318
1319   if(!myContainers.isEmpty())     
1320     crv->addOwners(myContainers);
1321   return crv;
1322 }
1323 /*!
1324   Restores curve object from stream
1325 */
1326 VISU::Storable* VISU::Curve_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr theSO)
1327 {
1328   if(MYDEBUG) MESSAGE(GetComment());
1329   mySObj = SALOMEDS::SObject::_duplicate(theSO);
1330   SetName(VISU::Storable::FindValue(theMap,"myName").toLatin1().data(), false);
1331   myHRow = VISU::Storable::FindValue(theMap,"myHRow").toInt();
1332   myVRow = VISU::Storable::FindValue(theMap,"myVRow").toInt();
1333   bool ok = false;
1334   QString z_str = VISU::Storable::FindValue(theMap,"myZRow", &ok);
1335   myZRow = ok ? z_str.toInt() : 0;
1336   ok = false;
1337   QString v2_str = VISU::Storable::FindValue(theMap,"myIsV2", &ok);
1338   myIsV2 = ok ? v2_str.toInt() : false;
1339
1340   QString scale_str = VISU::Storable::FindValue(theMap,"myScale", &ok);
1341   myScale = ok ? scale_str.toDouble() : 1.0;
1342   myColor.R = VISU::Storable::FindValue(theMap,"myColor.R").toDouble();
1343   myColor.G = VISU::Storable::FindValue(theMap,"myColor.G").toDouble();
1344   myColor.B = VISU::Storable::FindValue(theMap,"myColor.B").toDouble();
1345   myMarker = ( VISU::Curve::MarkerType )( VISU::Storable::FindValue(theMap,"myMarker").toInt() );
1346   myLine = ( VISU::Curve::LineType )( VISU::Storable::FindValue(theMap,"myLine").toInt() );
1347   myLineWidth = VISU::Storable::FindValue(theMap,"myLineWidth").toInt();
1348   myAuto = VISU::Storable::FindValue(theMap,"myAuto").toInt();
1349   return Build( true );
1350 }
1351 /*!
1352   Flushes curve data into stream
1353 */
1354 void VISU::Curve_i::ToStream( std::ostringstream& theStr )
1355 {
1356   Storable::DataToStream( theStr, "myName",      GetName().c_str() );
1357   Storable::DataToStream( theStr, "myHRow",      myHRow );
1358   Storable::DataToStream( theStr, "myVRow",      myVRow );
1359   Storable::DataToStream( theStr, "myZRow",      myZRow );
1360   Storable::DataToStream( theStr, "myIsV2",      myIsV2 );
1361   Storable::DataToStream( theStr, "myScale",     myScale );
1362   Storable::DataToStream( theStr, "myColor.R",   myColor.R );
1363   Storable::DataToStream( theStr, "myColor.G",   myColor.G );
1364   Storable::DataToStream( theStr, "myColor.B",   myColor.B );
1365   Storable::DataToStream( theStr, "myMarker",    myMarker );
1366   Storable::DataToStream( theStr, "myLine",      myLine );
1367   Storable::DataToStream( theStr, "myLineWidth", myLineWidth );
1368   Storable::DataToStream( theStr, "myAuto",      myAuto );
1369 }
1370 /*!
1371   Gets reference table's entry
1372 */
1373 std::string VISU::Curve_i::GetTableID() {
1374   return myTable->GetObjectEntry();
1375 }
1376 /*!
1377   Called from engine to restore curve from the file
1378 */
1379 VISU::Storable* VISU::Curve_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
1380                                               const Storable::TRestoringMap& theMap,
1381                                               const std::string& thePrefix,
1382                                               CORBA::Boolean theIsMultiFile)
1383 {
1384   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
1385   VISU::Table_i* pTable = GetTable(aStudy, theSObject->GetFather());
1386   if( pTable != NULL ) {
1387     VISU::Curve_i* pResent = new VISU::Curve_i( aStudy, pTable, 0, 0, 0, false );
1388     return pResent->Restore( theMap, theSObject);
1389   }
1390   return NULL;
1391 }
1392
1393 void VISU::Curve_i::RemoveFromStudy()
1394 {
1395   
1396   //remove curve from containers
1397   PortableServer::POA_ptr aPOA = GetPOA();
1398   ContainerSet::ConstIterator it = myContainers.begin();
1399   for ( ; it != myContainers.end(); it++ ) {    
1400     SALOMEDS::SObject_var aSObject =  GetStudyDocument()->FindObjectID( (*it).toLatin1().data() );
1401     if ( aSObject->_is_nil() ) continue;
1402     
1403     CORBA::Object_var anObj = VISU::SObjectToObject( aSObject );
1404     if ( CORBA::is_nil( anObj ) ) continue;
1405     VISU::Container_i* aContainer = dynamic_cast<VISU::Container_i*>( VISU::GetServant( anObj.in() ).in() );
1406     if ( !aContainer ) continue;
1407     aContainer->RemoveCurve(VISU::Curve::_narrow(aPOA->servant_to_reference(this)));
1408   }
1409
1410   struct TRemoveFromStudy: public SALOME_Event
1411   {
1412     VISU::Curve_i* myRemovable;
1413     TRemoveFromStudy(VISU::Curve_i* theRemovable):
1414       myRemovable(theRemovable)
1415     {}
1416     
1417     virtual
1418     void
1419     Execute()
1420     {
1421       VISU::DeleteActors(myRemovable);
1422       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
1423     }
1424   };
1425
1426   ProcessVoidEvent(new TRemoveFromStudy(this));
1427 }
1428
1429 SALOMEDS::SObject_var VISU::Curve_i::GetSObject()
1430 {
1431   return mySObj;
1432 }
1433
1434
1435 /*!
1436   Add container.
1437   id  - owner of the curve
1438 */
1439 void VISU::Curve_i::addContainer(const QString& id) {
1440   myContainers.insert(id);
1441 }
1442
1443 /*!
1444   Remove Container
1445   id  - entry of the container
1446 */
1447 void VISU::Curve_i::removeContainer(const QString& id) {
1448   myContainers.insert(id);
1449 }
1450
1451 /*!
1452   Get all owners of the curve.
1453   \return owners of the curve.
1454 */
1455 VISU::ContainerSet VISU::Curve_i::getContainers() const {
1456   return myContainers;
1457 }
1458
1459 /*!
1460   Return true if on the curve were assigned deviation data
1461 */
1462 bool VISU::Curve_i::hasDeviation() {
1463   return myTable && myTable->hasDeviationData(myVRow-1);
1464 }
1465
1466 /*!
1467   Enable/disable deviation data displaying.
1468 */
1469 void  VISU::Curve_i::ShowDeviation(CORBA::Boolean flag) {
1470   if(flag && hasDeviation())
1471     myDeviationEnabled = flag;
1472   else
1473     myDeviationEnabled = false;
1474 }
1475 /*!
1476   Return enable deviation flag
1477 */
1478 bool VISU::Curve_i::isDeviationShown() {
1479   return myDeviationEnabled;
1480 }
1481
1482 //----------------------------------------------------------------
1483 //                      Container Object
1484 //----------------------------------------------------------------
1485 int VISU::Container_i::myNbPresent = 0;
1486 const string VISU::Container_i::myComment  = "CONTAINER";
1487 /*!
1488   Generate unique name
1489 */
1490 QString VISU::Container_i::GenerateName()
1491 {
1492   return VISU::GenerateName( "Plot2DView", ++myNbPresent ).toLatin1().data();
1493 }
1494 /*!
1495   Gets comment string
1496 */
1497 const char* VISU::Container_i::GetComment() const
1498 {
1499   return myComment.c_str();
1500 }
1501 /*!
1502   Constructor
1503 */
1504 VISU::Container_i::Container_i( SALOMEDS::Study_ptr theStudy )
1505      : PrsObject_i( theStudy )
1506 {
1507 }
1508 /*!
1509   Destructor
1510 */
1511 VISU::Container_i::~Container_i()
1512 {
1513   MESSAGE("Container_i::~Container_i");
1514   myCurves.clear();
1515 }
1516 /*!
1517   Inserts curve into the container
1518 */
1519 void VISU::Container_i::AddCurve( Curve_ptr theCurve )
1520 {
1521   if ( GetStudyDocument()->_is_nil() )
1522     return;
1523   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1524   if ( mySO->_is_nil() )
1525     return;
1526   PortableServer::POA_ptr aPOA = GetPOA();
1527   Curve_i* pCurve = dynamic_cast<Curve_i*>( aPOA->reference_to_servant( theCurve ) );
1528   if( pCurve ) {
1529     QString entry( pCurve->GetEntry().c_str() );
1530     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( entry.toLatin1().data() );
1531     if ( !SO->_is_nil() && myCurves.indexOf( entry ) == -1 ) {
1532       myCurves.append( entry );
1533       SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1534       SALOMEDS::SObject_var newSO = Builder->NewObject( mySO );
1535       Builder->Addreference( newSO, SO );
1536       pCurve->addContainer(GetEntry().c_str());
1537     }
1538   }
1539 }
1540 /*!
1541   Removes curve from the container
1542 */
1543 void VISU::Container_i::RemoveCurve( Curve_ptr theCurve )
1544 {
1545   if ( GetStudyDocument()->_is_nil() )
1546     return;
1547   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1548   if ( mySO->_is_nil() )
1549     return;
1550   PortableServer::POA_ptr aPOA = GetPOA();
1551   Curve_i* pCurve = dynamic_cast<Curve_i*>( aPOA->reference_to_servant( theCurve ) );
1552   if( pCurve ) {
1553     QString entry( pCurve->GetEntry().c_str() );
1554     if ( myCurves.indexOf( entry ) != -1 ) {
1555       // found !!!
1556       myCurves.removeAll( entry );
1557       SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1558       SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1559       for ( ; CI->More(); CI->Next() ) {
1560         SALOMEDS::SObject_var childSO = CI->Value();
1561         SALOMEDS::SObject_var refSO;
1562         if ( childSO->ReferencedObject( refSO ) && !refSO->_is_nil() && entry == QString( refSO->GetID() ) ) {
1563           Builder->RemoveObject( childSO );
1564         }
1565       }
1566       pCurve->removeContainer(GetEntry().c_str());
1567     }
1568   }
1569 }
1570 /*!
1571   Gets number of curves in the container
1572 */
1573 CORBA::Long VISU::Container_i::GetNbCurves()
1574 {
1575   //  Update();
1576   return myCurves.count();
1577 }
1578 /*!
1579   Clears container
1580 */
1581 void VISU::Container_i::Clear()
1582 {
1583   if ( GetStudyDocument()->_is_nil() )
1584     return;
1585   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1586   if ( mySO->_is_nil() )
1587     return;
1588   QStringList toDelete;
1589   SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1590   for ( ; CI->More(); CI->Next() ) {
1591     toDelete.append( CI->Value()->GetID() );
1592   }
1593   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1594   for ( int i = 0; i < toDelete.count(); i++ ) {
1595     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( toDelete[i].toLatin1().data() );
1596     Builder->RemoveObject( SO );
1597   }
1598   myCurves.clear();
1599 }
1600 /*!
1601   Creates container object
1602 */
1603 VISU::Storable* VISU::Container_i::Create()
1604 {
1605   // generate name ...
1606   SetName(GenerateName().toLatin1().data(), false);
1607   // ... and build the object
1608   return Build( false );
1609 }
1610 /*!
1611   Builds presentation of container
1612 */
1613 VISU::Storable* VISU::Container_i::Build( int theRestoring )
1614 {
1615   if ( !theRestoring ) {
1616     // looking for component
1617     SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
1618     // create SObject and set attributes
1619     QString aComment;
1620     aComment.sprintf("myComment=%s",GetComment());
1621     string anEntry = CreateAttributes( GetStudyDocument(),
1622                                        SComponent->GetID(),
1623                                        "",
1624                                        GetID(),
1625                                        GetName(),
1626                                        "",
1627                                        aComment.toLatin1().data(),
1628                                        true );
1629     mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID(anEntry.c_str()));
1630
1631     // Set icon
1632     SALOMEDS::StudyBuilder_var aStudyBuilder = GetStudyDocument()->NewBuilder();
1633     SALOMEDS::GenericAttribute_var anAttr;
1634     SALOMEDS::AttributePixMap_var  aPixmap;
1635     anAttr  = aStudyBuilder->FindOrCreateAttribute( mySObj, "AttributePixMap" );
1636     aPixmap = SALOMEDS::AttributePixMap::_narrow( anAttr );
1637     aPixmap ->SetPixMap("ICON_TREE_CONTAINER");
1638   }
1639   return this;
1640 }
1641 /*!
1642   Updates presentation of container
1643 */
1644 void VISU::Container_i::Update()
1645 {
1646   if ( GetStudyDocument()->_is_nil() )
1647     return;
1648   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1649   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1650   SALOMEDS::GenericAttribute_var anAttr;
1651   if ( !mySO->_is_nil() ) {
1652     QStringList toDelete;
1653     int i;
1654     for ( i = 0; i < myCurves.count(); i++ ) {
1655       SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( myCurves[i].toLatin1().data() );
1656       if ( !SO->_is_nil() && Builder->FindAttribute( SO, anAttr, "AttributeIOR" ) ) {
1657         // if real Curve Object still exists
1658         SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1659         bool bFound = false;
1660         for ( ; CI->More(); CI->Next() ) {
1661           SALOMEDS::SObject_var childSO = CI->Value();
1662           SALOMEDS::SObject_var refSO;
1663           if ( childSO->ReferencedObject( refSO ) && !refSO->_is_nil() && myCurves[i] == QString( refSO->GetID() ) ) {
1664             bFound = true; break;
1665           }
1666         }
1667         if (! bFound ) {
1668           // create SObject referenced to real curve object if is not yet added
1669           SALOMEDS::SObject_var newSO = Builder->NewObject( mySO );
1670           Builder->Addreference( newSO, SO );
1671         }
1672       }
1673       else {
1674         // real Curve Object doesn't exist (might be removed)
1675         toDelete.append( myCurves[i] );
1676       }
1677     }
1678     for ( i = 0; i < toDelete.count(); i++ ) {
1679       myCurves.removeAll( toDelete[i] );
1680     }
1681     toDelete.clear();
1682     SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1683     for ( ; CI->More(); CI->Next() ) {
1684       SALOMEDS::SObject_var childSO = CI->Value();
1685       SALOMEDS::SObject_var refSO;
1686       if ( childSO->ReferencedObject( refSO ) && ( refSO->_is_nil() || !Builder->FindAttribute( refSO, anAttr, "AttributeIOR" ) ||
1687                                                    myCurves.indexOf( refSO->GetID() ) == -1 ) ) {
1688         toDelete.append( childSO->GetID() );
1689       }
1690     }
1691     for ( i = 0; i < toDelete.count(); i++ ) {
1692       SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1693       for ( ; CI->More(); CI->Next() ) {
1694         SALOMEDS::SObject_var childSO = CI->Value();
1695         if ( toDelete[i] == CI->Value()->GetID() ) {
1696           Builder->RemoveObject( childSO );
1697         }
1698       }
1699     }
1700   }
1701 }
1702 /*!
1703   Gets curve from container by index
1704   NB : curves are numbered from 1
1705 */
1706 VISU::Curve_i* VISU::Container_i::GetCurve( CORBA::Long theIndex )
1707 {
1708   if ( theIndex > 0 && theIndex <= myCurves.count()  ) {
1709     SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1710     SALOMEDS::GenericAttribute_var anAttr;
1711     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myCurves[ theIndex-1 ].toLatin1().data() );
1712     CORBA::Object_var anObject = VISU::SObjectToObject( SO );
1713     if( !CORBA::is_nil( anObject ) ) {
1714       // if real Curve Object exists
1715       CORBA::Object_ptr aCurve = VISU::Curve::_narrow( anObject );
1716       if( !CORBA::is_nil( aCurve ) )
1717       return dynamic_cast<VISU::Curve_i*>(VISU::GetServant(aCurve).in());
1718     }
1719   }
1720   return NULL;
1721 }
1722 /*!
1723   Restores container data from the stream
1724 */
1725 VISU::Storable* VISU::Container_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr SO )
1726 {
1727   if(MYDEBUG) MESSAGE(GetComment());
1728   mySObj = SALOMEDS::SObject::_duplicate(SO);
1729   SetName(VISU::Storable::FindValue( theMap, "myName" ).toLatin1().data(), false);
1730   QString val = VISU::Storable::FindValue( theMap, "myCurves" );
1731   myCurves = val.split( "*", QString::SkipEmptyParts );
1732   return Build( true );
1733 }
1734 /*!
1735   Flushes container data into the stream
1736 */
1737 void VISU::Container_i::ToStream( std::ostringstream& theStr )
1738 {
1739   Storable::DataToStream( theStr, "myName",   GetName().c_str() );
1740   Storable::DataToStream( theStr, "myCurves", myCurves.join( QString( "*" ) ) );
1741 //  theStr<<" myName "<<myName;
1742 //  theStr<<" myCurves "<<myCurves.join( QString( "*" ) ).latin1()<<"* ";
1743 }
1744 /*!
1745   Called from engine to restore container from the file
1746 */
1747 VISU::Storable* VISU::Container_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
1748                                                   const Storable::TRestoringMap& theMap,
1749                                                   const std::string& thePrefix,
1750                                                   CORBA::Boolean theIsMultiFile)
1751 {
1752   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
1753   VISU::Container_i* pResent = new VISU::Container_i( aStudy );
1754   return pResent->Restore( theMap, theSObject );
1755 }
1756
1757 void VISU::Container_i::RemoveFromStudy()
1758 {
1759   struct TRemoveFromStudy: public SALOME_Event
1760   {
1761     VISU::Container_i* myRemovable;
1762     TRemoveFromStudy(VISU::Container_i* theRemovable):
1763       myRemovable(theRemovable)
1764     {}
1765     
1766     virtual
1767     void
1768     Execute()
1769     {
1770       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
1771     }
1772   };
1773
1774   ProcessVoidEvent(new TRemoveFromStudy(this));
1775 }
1776
1777 SALOMEDS::SObject_var VISU::Container_i::GetSObject()
1778 {
1779   return mySObj;
1780 }
1781
1782 SALOMEDS::SObject_var
1783 VISU::ImportTables(const char* theFileName, SALOMEDS::Study_ptr theStudy,
1784                    bool theFirstStrAsTitle)
1785 {
1786   // Set "C" numeric locale to import numbers correctly
1787   Kernel_Utils::Localizer loc;
1788
1789   TTableContainer aContainer;
1790   ImportTables( theFileName, aContainer, theFirstStrAsTitle );
1791   if ( aContainer.empty() ) 
1792     return SALOMEDS::SObject::_nil();
1793
1794   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
1795   SALOMEDS::SComponent_var theSComponent = VISU::FindOrCreateVisuComponent(theStudy);
1796   SALOMEDS::SObject_var aFileObject = aStudyBuilder->NewObject(theSComponent);
1797   SALOMEDS::GenericAttribute_var anAttr =
1798     aStudyBuilder->FindOrCreateAttribute(aFileObject, "AttributeName");
1799   SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
1800   QFileInfo aFileInfo(theFileName);
1801   aName->SetValue( aFileInfo.fileName().toLatin1().data());
1802   anAttr = aStudyBuilder->FindOrCreateAttribute(aFileObject, "AttributeString");
1803   SALOMEDS::AttributeString_var aComment = SALOMEDS::AttributeString::_narrow(anAttr);
1804   QString aString;
1805   aString.sprintf("myComment=ImportTables;myFileName=%s;myFirstStrAsTitle=%d",
1806                   aFileInfo.absoluteFilePath().toLatin1().data(),theFirstStrAsTitle);
1807   aComment->SetValue(aString.toLatin1().data());
1808   for(int i = 0, iEnd = aContainer.size(); i < iEnd; i++) {
1809     PTableIDMapper aTableIDMapper = aContainer[i];
1810     const TTable2D& aTable2D = *aTableIDMapper;
1811     SALOMEDS::SObject_var aRealObject = aStudyBuilder->NewObject(aFileObject);
1812     anAttr = aStudyBuilder->FindOrCreateAttribute(aRealObject, "AttributeName");
1813     aName = SALOMEDS::AttributeName::_narrow(anAttr);
1814     if(MYDEBUG) MESSAGE("aTable2D.myTitle = "<<aTable2D.myTitle);
1815     if ( aTable2D.myTitle != "" ) {
1816       aName->SetValue(aTable2D.myTitle.c_str());
1817     }
1818     else {
1819       QString aNewName;
1820       aNewName.sprintf("Table:%d",i);
1821       aName->SetValue(aNewName.toLatin1().data());
1822     }
1823
1824     anAttr = aStudyBuilder->FindOrCreateAttribute(aRealObject, "AttributeTableOfReal");
1825     SALOMEDS::AttributeTableOfReal_var aTableOfReal = SALOMEDS::AttributeTableOfReal::_narrow(anAttr);
1826     aTableOfReal->SetTitle(aTable2D.myTitle.c_str());
1827     TTable2D aNewTable2D;
1828     aTable2D.getColumns(aNewTable2D);
1829     int kEnd = aNewTable2D.myRows[0].myValues.size();
1830     // check empty columns
1831     TColStd_MapOfInteger EmptyColumns;
1832     for(int j = 0, jEnd = aNewTable2D.myRows.size(); j < jEnd; j++) {
1833       bool hasVal = false;
1834       for(int k = 0; k < kEnd; k++) {
1835         QString aVal = aNewTable2D.myRows[j].myValues[k].c_str();
1836         bool anIsOk = false;
1837         double aValue = aVal.toDouble(&anIsOk);
1838         if(anIsOk) {
1839           hasVal = true;
1840           break;
1841         }
1842       }
1843       if(!hasVal) {
1844         EmptyColumns.Add(j);
1845       }
1846     }
1847     // create table of real
1848     aTableOfReal->SetNbColumns( kEnd - EmptyColumns.Extent() );
1849     int currNum = -1;
1850     for(int j = 0, jEnd = aNewTable2D.myRows.size(); j < jEnd; j++) {
1851       if( EmptyColumns.Contains(j) ) continue;
1852       currNum++;
1853       if(MYDEBUG) MESSAGE("j = "<<j<<"; kEnd = "<<kEnd);
1854       for(int k = 0; k < kEnd; k++) {
1855         QString aVal = aNewTable2D.myRows[j].myValues[k].c_str();
1856         bool anIsOk = false;
1857         double aValue = aVal.toDouble(&anIsOk);
1858         if( anIsOk && !aVal.contains("NAN",Qt::CaseInsensitive) &&
1859             !aVal.contains("INF",Qt::CaseInsensitive) ) {
1860           aTableOfReal->PutValue(aValue,currNum+1,k+1);
1861         }
1862       }
1863       aTableOfReal->SetRowTitle(currNum+1,aNewTable2D.myRows[j].myTitle.c_str());
1864       aTableOfReal->SetRowUnit(currNum+1,aNewTable2D.myRows[j].myUnit.c_str());
1865     }
1866     for(int k = 0; k < kEnd; k++)
1867       aTableOfReal->SetColumnTitle(k+1,aNewTable2D.myColumnTitles[k].c_str());
1868   }
1869   return aFileObject;
1870 }
1871
1872
1873 //=======================================================================
1874 //function : updateStrForCSV
1875 //purpose  : auxilary for ExportTableToFile
1876 //=======================================================================
1877 void updateStrForCSV(QString& aStr, const char aSep)
1878 {
1879   int index = aStr.indexOf('"');
1880   while(index>=0) {
1881     aStr.insert(index,'"');
1882     if( index+2 >= aStr.size() ) break;
1883     index = aStr.indexOf('"',index+2);
1884   }
1885   index = aStr.indexOf(aSep);
1886   if(index>=0) {
1887     // current string contains separator => need to use "..."
1888     aStr.insert(0,'"');
1889     aStr.push_back('"');
1890   }
1891 }
1892
1893
1894 //=======================================================================
1895 //function : ExportTableToFile
1896 //purpose  : 
1897 //=======================================================================
1898 template<class TTableAttr> bool ExportTableToFile(const TTableAttr& aTabAttr,
1899                                                   const char* theFileName)
1900 {
1901   if (CORBA::is_nil(aTabAttr))
1902     return false;
1903
1904   // Set "C" numeric locale to save numbers correctly
1905   Kernel_Utils::Localizer loc;
1906
1907   QFile aFile(theFileName);
1908   aFile.open(QIODevice::WriteOnly);
1909
1910   /* extract the table info and write it into file */
1911
1912   QString aTitle(aTabAttr->GetTitle()); /*Table title*/
1913   int aRowsNb = aTabAttr->GetNbRows();
1914   int aColNb  = aTabAttr->GetNbColumns();
1915
1916   SALOMEDS::StringSeq_var aRowTitles = aTabAttr->GetRowTitles();
1917   SALOMEDS::StringSeq_var aRowUnits = aTabAttr->GetRowUnits();
1918   SALOMEDS::StringSeq_var aColumnTitles = aTabAttr->GetColumnTitles();
1919
1920   //--------------------------------------------------
1921   //    write as *.csv file if it is needed
1922   //--------------------------------------------------
1923   QString tmp(theFileName);
1924   tmp = tmp.trimmed();
1925   tmp = tmp.right(3).trimmed();
1926   if( tmp == QString("csv") ) {
1927     const char aSep = ',';
1928     // write column titles
1929     QString aLine(aRowTitles[0]);
1930     updateStrForCSV(aLine,aSep);
1931     for(int i=1; i<aRowsNb; i++) {
1932       aLine += aSep;
1933       QString aTmp(aRowTitles[i]);
1934       updateStrForCSV(aTmp,aSep);
1935       aLine += aTmp;
1936     }
1937     aLine += "\n";
1938     aFile.write(aLine.toLatin1() );
1939     // write table data
1940     QString aValue;
1941     for (int j = 1; j <= aColNb; j++) {
1942       QString aLine = "";
1943       if(aTabAttr->HasValue(1,j)) {
1944         aLine = aValue.sprintf("%.16g",(double)aTabAttr->GetValue(1,j));
1945       }
1946       for (int i = 2; i <= aRowsNb; i++) {
1947         if(aTabAttr->HasValue(i,j)) {
1948           aLine += aSep + aValue.sprintf("%.16g",(double)aTabAttr->GetValue(i,j));
1949         }
1950         else aLine += aSep;
1951       }
1952       aLine += "\n";
1953       aFile.write(aLine.toLatin1() );
1954     }
1955
1956     aFile.close();
1957     return true;
1958   }
1959   //--------------------------------------------------
1960   //       end of writing as *.csv file
1961   //--------------------------------------------------
1962
1963   /* The given table is rare (some cells is empty) or not? */
1964   bool isRareTable = false;
1965   for (int i = 1; i <= aRowsNb; i++)
1966     for (int j = 1; j <= aColNb && !isRareTable; j++)
1967       isRareTable = !aTabAttr->HasValue(i,j);
1968
1969   QString aLine;
1970   if (isRareTable) {
1971     /* Separate the given table to 2D tables and write these ones to the file */
1972     QString anAbscissTitle(aRowTitles[0]); /*Absciss row title (X coord)*/
1973     anAbscissTitle.trimmed();
1974     QString anAbscissUnit(aRowUnits[0]);
1975     anAbscissUnit.trimmed();
1976     if (aRowsNb > 2 && aTitle.length() )  aTitle = aTitle + " - ";
1977
1978     for (int i = 2; i <= aRowsNb; i++ )
1979       {
1980         /* TITLE */
1981         QString anOrdinate(aRowTitles[i-1]), aTail;
1982         anOrdinate.trimmed();
1983
1984         aLine = "#TITLE: " + aTitle +
1985           ((anOrdinate.length())?  anOrdinate :
1986                                   (aRowsNb>2)? aTail.sprintf("%d",i-1) : aTail.sprintf("") ) + "\n";
1987         aFile.write(aLine.toLatin1() );
1988
1989         /* COLUMN_TITLES */
1990         if ( anAbscissTitle.length() || anOrdinate.length() ) {
1991           aLine = "#COLUMN_TITLES: " + anAbscissTitle + " | " + anOrdinate;
1992           int tmpind = aLine.indexOf("\n");
1993           while(tmpind>=0) {
1994             aLine.remove(tmpind,1);
1995             tmpind = aLine.indexOf("\n");
1996           }
1997           aLine += "\n";
1998           aFile.write(aLine.toLatin1() );
1999         }
2000
2001         /* COLUMN_UNITS */
2002         aLine = anAbscissUnit + " " +aRowUnits[i-1];
2003         if (!aLine.trimmed().isEmpty()) {
2004           aLine = "#COLUMN_UNITS: " + aLine  + "\n";
2005           aFile.write(aLine.toLatin1() );
2006         }
2007
2008         /* CURVE COORDINATES */
2009         for (int j = 1; j <= aColNb; j++)
2010           {
2011             if ( aTabAttr -> HasValue(i,j) &&  aTabAttr -> HasValue(1, j)) {
2012               aLine = aLine.sprintf("%.16g %.16g",
2013                                     (double)(aTabAttr->GetValue(1,j)),
2014                                     (double)(aTabAttr->GetValue(i,j)));  /* aTabAttr->GetValue(1,j) - X coord */
2015               if ( !aLine.trimmed().isEmpty() ) {
2016                 QString aColTitle(aColumnTitles[j-1]);
2017                 if ( !aColTitle.trimmed().isEmpty() )
2018                   aLine = aLine + "  #TITLE: " + aColTitle ;
2019                 aFile.write(QString(aLine + "\n").toLatin1() );
2020               }
2021             }
2022           }
2023         aFile.write("\n", 1);
2024       }
2025   }//end of if (isRareTable)
2026   else {
2027     /* Write the table in the file without separating */
2028     /* TITLE */
2029     aLine = "#TITLE: " + aTitle + "\n";
2030     aFile.write(aLine.toLatin1());
2031
2032     /* COLUMN_TITLES  and COLUMN_UNITS */
2033     QString aTitlesSep = "";
2034     QString aUnitsSep  = "";
2035     QString aTitlesStr = "#COLUMN_TITLES: ";
2036     QString aUnitsStr  = "#COLUMN_UNITS: ";
2037     for (int i = 1; i <= aRowsNb; i++) {
2038       if (!QString(aRowTitles[i-1]).trimmed().isEmpty()) {
2039         aTitlesStr += (aTitlesSep + aRowTitles[i-1]);
2040         if (aTitlesSep.isEmpty()) aTitlesSep = " | ";
2041       }
2042       if (!QString(aRowUnits[i-1]).trimmed().isEmpty()) {
2043         aUnitsStr += (aUnitsSep + aRowUnits[i-1]);
2044         if (aUnitsSep.isEmpty()) aUnitsSep = " ";
2045       }
2046     }
2047     int tmpind = aTitlesStr.indexOf("\n");
2048     while(tmpind>=0) {
2049       aTitlesStr.remove(tmpind,1);
2050       tmpind = aTitlesStr.indexOf("\n");
2051     }
2052     aTitlesStr += "\n";
2053     aUnitsStr  += "\n";
2054     aFile.write(aTitlesStr.toLatin1());
2055     aFile.write(aUnitsStr.toLatin1());
2056
2057     /* CURVE COORDINATES */
2058     QString aSep, aValue, aColTitle;
2059     for (int j = 1; j <= aColNb; j++) {
2060       aLine = ""; aSep  = "";
2061       for (int i = 1; i <= aRowsNb; i++) {
2062         aLine += (aSep + aValue.sprintf("%.16g", (double)(aTabAttr->GetValue(i,j))));
2063         if (aSep.isEmpty()) aSep = " ";
2064       }
2065       if (!aLine.trimmed().isEmpty()) {
2066         aColTitle = aColumnTitles[j-1];
2067         if (!aColTitle.trimmed().isEmpty())
2068           aLine = aLine + "  #TITLE: " + aColTitle;
2069         aLine += "\n";
2070         aFile.write(aLine.toLatin1());
2071       }
2072     }
2073   } //end of else
2074
2075   aFile.close();
2076   return true;
2077 }
2078
2079 bool VISU::ExportTableToFile(SALOMEDS::SObject_ptr theTable, const char* theFileName)
2080 {
2081   //Find table
2082   SALOMEDS::GenericAttribute_var anAttr ;
2083   if (theTable->FindAttribute(anAttr, "AttributeTableOfReal")) {
2084     SALOMEDS::AttributeTableOfReal_var aTabAttr =
2085       SALOMEDS::AttributeTableOfReal ::_narrow(anAttr);
2086     return ExportTableToFile ( aTabAttr , theFileName);
2087   }
2088   else if (theTable->FindAttribute(anAttr, "AttributeTableOfInteger")) {
2089     SALOMEDS::AttributeTableOfInteger_var aTabAttr =
2090       SALOMEDS::AttributeTableOfInteger ::_narrow(anAttr);
2091     return ExportTableToFile ( aTabAttr , theFileName);
2092   }
2093   return false;
2094 }