Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/visu.git] / src / VISU_I / VISU_Table_i.cc
1 //  VISU OBJECT : interactive object for VISU entities implementation
2 //
3 //  Copyright (C) 2003  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 //  File   : VISU_Table_i.cc
24 //  Author : Vadim SANDLER
25 //  Module : VISU
26
27 #include "VISU_Table_i.hh"
28
29 #include "VISU_CutLines_i.hh"
30 #include "VISU_Result_i.hh"
31 #include "VISU_ViewManager_i.hh"
32
33 #include "SALOME_Event.hxx"
34 #include "SPlot2d_Curve.h"
35
36 #include <memory>
37 #include <fstream>
38 #include <strstream>
39
40 #include <qfileinfo.h>
41 #include <qstring.h>
42 #include <qregexp.h>
43 #include <qfile.h>
44
45 using namespace std;
46
47 #ifdef _DEBUG_
48 static int MYDEBUG = 0;
49 #else
50 static int MYDEBUG = 0;
51 #endif
52 //----------------------------------------------------------------
53 //                      Table Object
54 //----------------------------------------------------------------
55 int VISU::Table_i::myNbPresent = 0;
56 const string VISU::Table_i::myComment  = "TABLE";
57 /*!
58   Generate unique name
59 */
60 QString VISU::Table_i::GenerateName()
61 {
62   return VISU::GenerateName( "Table", ++myNbPresent );
63 }
64 /*!
65   Gets comment string
66 */
67 const char* VISU::Table_i::GetComment() const
68 {
69   return myComment.c_str();
70 }
71 /*!
72   Constructor
73 */
74 VISU::Table_i::Table_i( SALOMEDS::Study_ptr theStudy, const char* theObjectEntry )
75      : PrsObject_i(theStudy)
76 {
77   mySObj = theStudy->FindObjectID(theObjectEntry);
78   myOrientation = VISU::Table::HORIZONTAL;
79 }
80 /*!
81   Destructor
82 */
83 VISU::Table_i::~Table_i()
84 {
85   MESSAGE("Table_i::~Table_i");
86 }
87
88 //----------------------------------------------------------------------------
89 void
90 VISU::Table_i
91 ::SetTitle( const char* theTitle )
92 {
93   SetName( theTitle, true );
94 }
95
96 //----------------------------------------------------------------------------
97 char*
98 VISU::Table_i
99 ::GetTitle()
100 {
101   return CORBA::string_dup( GetName().c_str() );
102 }
103
104 //----------------------------------------------------------------------------
105 void
106 VISU::Table_i
107 ::SetOrientation( VISU::Table::Orientation theOrientation )
108 {
109   myOrientation = theOrientation;
110 }
111
112 //----------------------------------------------------------------------------
113 VISU::Table::Orientation
114 VISU::Table_i
115 ::GetOrientation()
116 {
117   return myOrientation;
118 }
119
120 //----------------------------------------------------------------------------
121 SALOMEDS::SObject_var
122 VISU::Table_i
123 ::GetSObject() const
124 {
125   return mySObj;
126 }
127
128 //----------------------------------------------------------------------------
129 std::string
130 VISU::Table_i
131 ::GetObjectEntry() 
132 {
133   CORBA::String_var anEntry = mySObj->GetID();
134   return anEntry.in(); 
135 }
136
137 //----------------------------------------------------------------------------
138 /*!
139   Gets number of rows in table
140 */
141 CORBA::Long VISU::Table_i::GetNbRows()
142 {
143   SALOMEDS::SObject_var SO = mySObj;
144   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
145   if ( !SO->_is_nil() ) {
146     SALOMEDS::GenericAttribute_var        anAttr;
147     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
148       SALOMEDS::AttributeTableOfInteger_var anInt =  SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
149         return anInt->GetNbRows();
150     }
151     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
152       SALOMEDS::AttributeTableOfReal_var aReal =  SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
153       return aReal->GetNbRows();
154     }
155   }
156   return 0;
157 }
158 /*!
159   Gets number of columns in table
160 */
161 CORBA::Long VISU::Table_i::GetNbColumns()
162 {
163   SALOMEDS::SObject_var SO = mySObj;
164   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
165   if ( !SO->_is_nil() ) {
166     SALOMEDS::GenericAttribute_var        anAttr;
167     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
168       SALOMEDS::AttributeTableOfInteger_var anInt =  SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
169       return anInt->GetNbColumns();
170     }
171     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
172       SALOMEDS::AttributeTableOfReal_var aReal =  SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
173       return aReal->GetNbColumns();
174     }
175   }
176   return 0;
177 }
178 /*!
179   Creates table object
180 */
181 VISU::Storable* VISU::Table_i::Create()
182 {
183   // generate name ...
184   SetName(GetTableTitle().latin1(), false);
185
186   // mpv (PAL 5357): if name attribute already exist at this label, use it as name of table
187   if ( GetName() == "" )
188     if ( !mySObj->_is_nil() ) {
189       CutLines_i* pCutLines = NULL;
190       CORBA::Object_var anObj = SObjectToObject(mySObj);
191       if(!CORBA::is_nil(anObj)){
192         VISU::CutLines_var aCutLines = VISU::CutLines::_narrow(anObj);
193           if(!aCutLines->_is_nil())
194             pCutLines = dynamic_cast<CutLines_i*>(GetServant(aCutLines).in());
195         }
196       if (!pCutLines)
197         if (mySObj->GetName()) SetName(mySObj->GetName(), false);
198     }
199
200   if ( GetName() == "" )
201     SetName(GenerateName().latin1(), false);
202   // ... and build the object
203   return Build( false );
204 }
205 /*!
206   Builds presentation of table
207 */
208 VISU::Storable* VISU::Table_i::Build( int theRestoring )
209 {
210
211   // look for reference SObject with table attribute
212   SALOMEDS::SObject_var SO = mySObj;
213
214   if ( !SO->_is_nil() ) {
215     CutLines_i* pCutLines = NULL;
216     CORBA::Object_var anObj = SObjectToObject(SO);
217     if(!CORBA::is_nil(anObj)){
218       VISU::CutLines_var aCutLines = VISU::CutLines::_narrow(anObj);
219       if(!aCutLines->_is_nil())
220         pCutLines = dynamic_cast<CutLines_i*>(GetServant(aCutLines).in());
221     }
222     SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
223     SALOMEDS::GenericAttribute_var anAttr;
224     // look for component
225     if ( !theRestoring ) {
226         SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
227         // create SObject and set attributes
228         QString aComment;
229         if(pCutLines)
230           aComment.sprintf("myComment=%s;mySourceId=CutLines",GetComment());
231         else{
232           aComment.sprintf("myComment=%s;mySourceId=TableAttr",GetComment());
233           SALOMEDS::SObject_var aFatherSObject = SO->GetFather();
234           if(aFatherSObject->FindAttribute(anAttr,"AttributeString")){
235             SALOMEDS::AttributeString_var aCommentAttr =
236               SALOMEDS::AttributeString::_narrow(anAttr);
237             CORBA::String_var aValue = aCommentAttr->Value();
238             Storable::TRestoringMap aMap;
239             Storable::StringToMap(aValue.in(),aMap);
240             bool anIsExist;
241             QString aMethodName = VISU::Storable::FindValue(aMap,"myComment",&anIsExist);
242             if(anIsExist){
243               if(strcmp(aMethodName.latin1(),"ImportTables") == 0){
244                 aComment.sprintf("myComment=%s;mySourceId=TableFile",GetComment());
245               }
246             }
247           }
248         }
249
250         string anEntry = CreateAttributes( GetStudyDocument(),
251                                           SO->GetID(),//SComponent->GetID(),
252                                           "ICON_TREE_TABLE",
253                                           GetID(),
254                                           GetName(),
255                                           "",
256                                           aComment.latin1(),
257                                           pCutLines );
258         // create SObject referenced to real table object
259         mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID( anEntry.c_str() ));
260         if(pCutLines) {
261           pCutLines->BuildTableOfReal(mySObj);
262         }
263         // mpv (PAL5357): reference attributes are unnecessary now
264         //SALOMEDS::SObject_var refSO = Builder->NewObject( mySObj );
265         //Builder->Addreference( refSO, SO );
266     }
267
268     return this;
269   }
270   return NULL;
271 }
272 /*!
273   Restores table object from stream
274 */
275 VISU::Storable* VISU::Table_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr SO)
276 {
277   if(MYDEBUG) MESSAGE(GetComment());
278   SetName(VISU::Storable::FindValue(theMap,"myName").latin1(), false);
279   myTitle = VISU::Storable::FindValue(theMap,"myTitle").latin1();
280   myOrientation = ( VISU::Table::Orientation )( VISU::Storable::FindValue(theMap,"myOrientation").toInt() );
281   mySObj = SALOMEDS::SObject::_duplicate(SO);
282   return Build( true );
283 }
284 /*!
285   Flushes table data into stream
286 */
287 void VISU::Table_i::ToStream( std::ostringstream& theStr )
288 {
289   Storable::DataToStream( theStr, "myName",        GetName().c_str() );
290   Storable::DataToStream( theStr, "myTitle",       myTitle.c_str() );
291   Storable::DataToStream( theStr, "myOrientation", myOrientation );
292 }
293 /*!
294   Called from engine to restore table from the file
295 */
296 VISU::Storable* VISU::Table_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
297                                               const Storable::TRestoringMap& theMap,
298                                               const std::string& thePrefix,
299                                               CORBA::Boolean theIsMultiFile)
300 {
301   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
302   VISU::Table_i* pResent = new VISU::Table_i( aStudy, "" );
303   return pResent->Restore( theMap, theSObject);
304 }
305 /*!
306   Gets title for the original table object
307 */
308 QString VISU::Table_i::GetTableTitle()
309 {
310   SALOMEDS::SObject_var SO = mySObj;
311   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
312   SALOMEDS::GenericAttribute_var        anAttr;
313   SALOMEDS::AttributeTableOfInteger_var anInt;
314   SALOMEDS::AttributeTableOfReal_var    aReal;
315   if ( !SO->_is_nil() ) {
316     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
317       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
318       CORBA::String_var aString = anInt->GetTitle();
319       return aString.in();
320     }
321     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
322       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
323       CORBA::String_var aString = aReal->GetTitle();
324       return aString.in();
325     }
326   }
327   return "";
328 }
329
330 //---------------------------------------------------------------
331 void VISU::Table_i::RemoveFromStudy()
332 {
333   struct TRemoveFromStudy: public SALOME_Event
334   {
335     VISU::Table_i* myRemovable;
336     TRemoveFromStudy(VISU::Table_i* theRemovable):
337       myRemovable(theRemovable)
338     {}
339     
340     virtual
341     void
342     Execute()
343     {
344       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
345     }
346   };
347
348   // Remove the table with all curves
349   ProcessVoidEvent(new TRemoveFromStudy(this));
350 }
351
352 //----------------------------------------------------------------
353 //                      Curve Object
354 //----------------------------------------------------------------
355 /*!
356   Restores table object from the stream [ static ]
357 */
358 static VISU::Table_i* GetTable( SALOMEDS::Study_ptr theStudy, SALOMEDS::SObject_ptr theSO ) {
359   CORBA::Object_var anObject = VISU::SObjectToObject( theSO );
360   if( !CORBA::is_nil( anObject ) ) {
361     CORBA::Object_ptr aTable = VISU::Table::_narrow( anObject );
362     if( !CORBA::is_nil( aTable ) )
363       return dynamic_cast<VISU::Table_i*>(VISU::GetServant(aTable).in());
364   }
365   return NULL;
366 }
367
368 int VISU::Curve_i::myNbPresent = 0;
369 const string VISU::Curve_i::myComment  = "CURVE";
370 /*!
371   Generate unique name
372 */
373 QString VISU::Curve_i::GenerateName()
374 {
375   return VISU::GenerateName( "Curve", ++myNbPresent );
376 }
377 /*!
378   Gets comment string
379 */
380 const char* VISU::Curve_i::GetComment() const
381 {
382   return myComment.c_str();
383 }
384 /*!
385   Constructor
386   NB : theHRow, theVRow are the indexes of rows in the Table object and numbered from the 1 to GetNbRows()
387 */
388 VISU::Curve_i::Curve_i( SALOMEDS::Study_ptr theStudy, Table_i* theTable,
389                         CORBA::Long theHRow, CORBA::Long theVRow,
390                         CORBA::Long theZRow )
391 : PrsObject_i(theStudy), myTable( theTable ), myHRow( theHRow ),
392   myVRow( theVRow ), myZRow( theZRow )
393 {
394   myAuto = true;
395   myLine = VISU::Curve::SOLIDLINE;
396   myLineWidth = 0;
397   myMarker = VISU::Curve::CIRCLE;
398   myColor.R = 0.0; myColor.G = 0.0; myColor.B = 0.0;
399 }
400 /*!
401   Destructor
402 */
403 VISU::Curve_i::~Curve_i()
404 {
405   MESSAGE("Curve_i::~Curve_i");
406 }
407
408 //----------------------------------------------------------------------------
409 void
410 VISU::Curve_i
411 ::SetTitle( const char* theTitle )
412 {
413   SetName( theTitle, true );
414 }
415
416 //----------------------------------------------------------------------------
417 char*
418 VISU::Curve_i
419 ::GetTitle()
420 {
421   return CORBA::string_dup( GetName().c_str() );
422 }
423
424 //----------------------------------------------------------------------------
425 void
426 VISU::Curve_i
427 ::SetColor( const SALOMEDS::Color& theColor )
428 {
429   myColor = theColor; 
430   myAuto = false;
431 }
432
433 //----------------------------------------------------------------------------
434 SALOMEDS::Color
435 VISU::Curve_i
436 ::GetColor()
437 {
438   return myColor;
439 }
440
441 //----------------------------------------------------------------------------
442 void
443 VISU::Curve_i
444 ::SetMarker( VISU::Curve::MarkerType theType )
445 {
446   myMarker = theType; 
447   myAuto = false;
448 }
449
450 //----------------------------------------------------------------------------
451 VISU::Curve::MarkerType
452 VISU::Curve_i
453 ::GetMarker()
454 {
455   return myMarker;
456 }
457
458 //----------------------------------------------------------------------------
459 void
460 VISU::Curve_i
461 ::SetLine( VISU::Curve::LineType theType, CORBA::Long theWidth )
462 {
463   myLine = theType; 
464   myLineWidth = theWidth; 
465   myAuto = false;
466 }
467
468 //----------------------------------------------------------------------------
469 VISU::Curve::LineType
470 VISU::Curve_i
471 ::GetLine()
472 {
473   return myLine;
474 }
475
476 //----------------------------------------------------------------------------
477 CORBA::Long
478 VISU::Curve_i
479 ::GetLineWidth()
480 {
481   return myLineWidth;
482 }
483
484 //----------------------------------------------------------------------------
485 /*!
486   Creates curve object
487 */
488 VISU::Storable* VISU::Curve_i::Create()
489 {
490   // generate name ...
491   SetName(GetVerTitle(), false);
492   if ( GetName() == "" )
493     SetName(GenerateName(), false);
494   // ... and build the object
495   return Build( false );
496 }
497 /*!
498   Builds presentation of curve
499 */
500 VISU::Storable* VISU::Curve_i::Build(int theRestoring )
501 {
502   if ( myTable != NULL ) {
503     // getting table SObject by it's entry
504     int nbRows = myTable->GetNbRows();
505     if ( myHRow > 0 && myHRow <= nbRows && myVRow > 0 && myVRow <= nbRows ) {
506       if ( !theRestoring ) {
507         // look for component
508         SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
509         // create SObject and set attributes
510         QString aComment;
511         aComment.sprintf("myComment=%s",GetComment());
512         string anEntry = CreateAttributes( GetStudyDocument(),
513                                           myTable->GetObjectEntry(),
514                                           "",
515                                           GetID(),
516                                           GetName(),
517                                           "",
518                                           aComment.latin1(),
519                                           true );
520         // create SObject referenced to real table object
521         mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID(anEntry.c_str()));
522       }
523       return this;
524     }
525   }
526   return NULL;
527 }
528
529 /*!
530   Returns CORBA::True if curve refers to valid table data
531 */
532 CORBA::Boolean VISU::Curve_i::IsValid()
533 {
534   // getting table SObject by it's entry
535   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
536   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
537   SALOMEDS::GenericAttribute_var        anAttr;
538   SALOMEDS::AttributeTableOfInteger_var anInt;
539   SALOMEDS::AttributeTableOfReal_var    aReal;
540   if ( !SO->_is_nil() ) {
541     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
542       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
543       if ( myHRow > 0 && myHRow <= anInt->GetNbRows() && myVRow > 0 && myVRow <= anInt->GetNbRows() ) {
544         return true;
545       }
546     }
547     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
548       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
549       if ( myHRow > 0 && myHRow <= aReal->GetNbRows() && myVRow > 0 && myVRow <= aReal->GetNbRows() ) {
550         return true;
551       }
552     }
553   }
554   return false;
555 }
556 /*!
557   Returns hor.axis title
558 */
559 string VISU::Curve_i::GetHorTitle()
560 {
561   string title;
562   // getting table SObject by it's entry
563   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
564   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
565   SALOMEDS::GenericAttribute_var        anAttr;
566   SALOMEDS::AttributeTableOfInteger_var anInt;
567   SALOMEDS::AttributeTableOfReal_var    aReal;
568   if ( !SO->_is_nil() ) {
569     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
570       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
571       SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
572       if ( rowTitles->length() > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() ) {
573         title = rowTitles[ myHRow-1 ];
574       }
575     }
576     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
577       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
578       SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
579       if ( rowTitles->length() > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() ) {
580         title = rowTitles[ myHRow-1 ];
581       }
582     }
583   }
584   return title;
585 }
586 /*!
587   Returns ver.axis title
588 */
589 string VISU::Curve_i::GetVerTitle()
590 {
591   string title;
592   // getting table SObject by it's entry
593   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
594   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
595   SALOMEDS::GenericAttribute_var        anAttr;
596   SALOMEDS::AttributeTableOfInteger_var anInt;
597   SALOMEDS::AttributeTableOfReal_var    aReal;
598   if ( !SO->_is_nil() ) {
599     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
600       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
601       SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
602       if ( rowTitles->length() > 0 && myVRow > 0 && myVRow <= anInt->GetNbRows() )
603         title = rowTitles[ myVRow-1 ];
604     }
605     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
606       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
607       SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
608       if ( rowTitles->length() > 0 && myVRow > 0 && myVRow <= aReal->GetNbRows() )
609         title = rowTitles[ myVRow-1 ];
610     }
611   }
612   return title;
613 }
614 /*!
615   Returns hor.axis units
616 */
617 string VISU::Curve_i::GetHorUnits()
618 {
619   string units;
620   // getting table SObject by it's entry
621   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
622   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
623   SALOMEDS::GenericAttribute_var        anAttr;
624   SALOMEDS::AttributeTableOfInteger_var anInt;
625   SALOMEDS::AttributeTableOfReal_var    aReal;
626   if ( !SO->_is_nil()  ) {
627     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
628       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
629       SALOMEDS::StringSeq_var rowUnits = anInt->GetRowUnits();
630       if ( rowUnits->length() > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() )
631         units = rowUnits[ myHRow-1 ];
632     }
633     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
634       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
635       SALOMEDS::StringSeq_var rowUnits = aReal->GetRowUnits();
636       if ( rowUnits->length() > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() )
637         units = rowUnits[ myHRow-1 ];
638     }
639   }
640   return units;
641 }
642 /*!
643   Returns ver.axis units
644 */
645 string VISU::Curve_i::GetVerUnits()
646 {
647   string units;
648   // getting table SObject by it's entry
649   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
650   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
651   SALOMEDS::GenericAttribute_var        anAttr;
652   SALOMEDS::AttributeTableOfInteger_var anInt;
653   SALOMEDS::AttributeTableOfReal_var    aReal;
654   if ( !SO->_is_nil() ) {
655     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
656       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
657       SALOMEDS::StringSeq_var rowUnits = anInt->GetRowUnits();
658       if ( rowUnits->length() > 0 && myVRow > 0 && myVRow <= anInt->GetNbRows() )
659         units = rowUnits[ myVRow-1];
660     }
661     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
662       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
663       SALOMEDS::StringSeq_var rowUnits = aReal->GetRowUnits();
664       if ( rowUnits->length() > 0 && myVRow > 0 && myVRow <= aReal->GetNbRows() )
665         units = rowUnits[ myVRow-1 ];
666     }
667   }
668   return units;
669 }
670 /*!
671   Gets curve data
672 */
673 int VISU::Curve_i::GetData( double*& theHorList, double*& theVerList, QStringList& zList )
674 {
675   theHorList = 0; theVerList = 0;
676   // getting table SObject by it's entry
677   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
678   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
679   SALOMEDS::GenericAttribute_var        anAttr;
680   SALOMEDS::AttributeTableOfInteger_var anInt;
681   SALOMEDS::AttributeTableOfReal_var    aReal;
682
683   QString tip = "%1: %2", z_data;
684
685   if ( !SO->_is_nil() ) {
686     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
687       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
688       int nbCols = anInt->GetNbColumns(), nbRows = anInt->GetNbRows();
689       if ( nbCols > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() && myVRow > 0 && myVRow <= anInt->GetNbRows() ) {
690         int nbPoints = 0;
691         for ( int j = 1; j <= nbCols; j++ ) {
692           if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) )
693             nbPoints++;
694         }
695         if ( nbPoints > 0 ) {
696           theHorList = new double[ nbPoints ];
697           theVerList = new double[ nbPoints ];
698           int k = 0;
699
700           SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
701
702           for ( int j = 1; j <= nbCols; j++ ) {
703             if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) ) {
704               theHorList[k] = anInt->GetValue( myHRow, j );
705               theVerList[k] = anInt->GetValue( myVRow, j );
706
707               z_data = tip.arg( GetHorTitle().c_str() ).arg( theHorList[k] ) + "\n";
708               z_data += tip.arg( GetVerTitle().c_str() ).arg( theVerList[k] );
709
710               if( myZRow>0 && myZRow<=nbRows && anInt->HasValue( myZRow, j ) )
711               {
712                 string title;
713                 title = rowTitles[ myZRow-1 ];
714                 z_data += "\n" + tip.arg( title.c_str() ).arg( anInt->GetValue( myZRow, j ) );
715               }
716               zList.append( z_data );
717               k++;
718             }
719           }
720         }
721         return nbPoints;
722       }
723     }
724     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
725       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
726       int nbCols = aReal->GetNbColumns(), nbRows = aReal->GetNbRows();
727       if ( nbCols > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() && myVRow > 0 && myVRow <= aReal->GetNbRows() ) {
728         int nbPoints = 0;
729         for ( int j = 1; j <= nbCols; j++ ) {
730           if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) )
731             nbPoints++;
732         }
733         if ( nbPoints > 0 ) {
734           theHorList = new double[ nbPoints ];
735           theVerList = new double[ nbPoints ];
736           int k = 0;
737
738           SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
739
740           for ( int j = 1; j <= nbCols; j++ ) {
741             if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) ) {
742               theHorList[k] = aReal->GetValue( myHRow, j );
743               theVerList[k] = aReal->GetValue( myVRow, j );
744
745               z_data = tip.arg( GetHorTitle().c_str() ).arg( theHorList[k] ) + "\n";
746               z_data += tip.arg( GetVerTitle().c_str() ).arg( theVerList[k] );
747
748               if( myZRow>0 && myZRow<=nbRows && aReal->HasValue( myZRow, j ) )
749               {
750                 string title;
751                 title = rowTitles[ myZRow-1 ];
752                 z_data += "\n" + tip.arg( title.c_str() ).arg( aReal->GetValue( myZRow, j ) );
753               }
754               zList.append( z_data );
755               k++;
756             }
757           }
758         }
759         return nbPoints;
760       }
761     }
762   }
763   return 0;
764 }
765 /*!
766   Creates curve Plot2d presentation object
767 */
768 SPlot2d_Curve* VISU::Curve_i::CreatePresentation()
769 {
770   SPlot2d_Curve* crv = new SPlot2d_Curve();
771   crv->setHorTitle( GetHorTitle().c_str() );
772   string tlt = GetTitle();
773   if ( tlt.length() <= 0 )
774     tlt = GetVerTitle();
775   //crv->setVerTitle( strdup( GetVerTitle().c_str() ) );
776   //crv->setVerTitle( strdup( GetName() ) );
777   crv->setVerTitle( tlt.c_str() );
778   crv->setHorUnits( GetHorUnits().c_str() );
779   crv->setVerUnits( GetVerUnits().c_str() );
780   double* xList = 0;
781   double* yList = 0;
782   QStringList zList;
783   int     nbPoints = GetData( xList, yList, zList );
784   if ( nbPoints > 0 && xList && yList ) {
785     crv->setData( xList, yList, nbPoints, zList );
786   }
787   //cout << "********** Number of points: " << nbPoints <<endl;
788   //for ( int i =0 ; i < nbPoints; i++ ) {
789   //  cout << i<<"\t"<<xList[i] << "\t"<< yList[i] << endl;
790   //}
791   crv->setLine( (Plot2d_Curve::LineType)GetLine(), GetLineWidth() );
792   crv->setMarker( (Plot2d_Curve::MarkerType)GetMarker() );
793   SALOMEDS::Color color = GetColor();
794   crv->setColor( QColor( (int)(color.R*255.), (int)(color.G*255.), (int)(color.B*255.) ) );
795   crv->setAutoAssign( IsAuto() );
796   CORBA::String_var aString = mySObj->GetID();
797   crv->setIO(new SALOME_InteractiveObject(aString.in(), "VISU", GetName().c_str()));
798   if ( myTable )
799     crv->setTableIO(new SALOME_InteractiveObject(myTable->GetObjectEntry().c_str(), "VISU", myTable->GetName().c_str()));
800   return crv;
801 }
802 /*!
803   Restores curve object from stream
804 */
805 VISU::Storable* VISU::Curve_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr theSO)
806 {
807   if(MYDEBUG) MESSAGE(GetComment());
808   mySObj = SALOMEDS::SObject::_duplicate(theSO);
809   SetName(VISU::Storable::FindValue(theMap,"myName").latin1(), false);
810   myHRow = VISU::Storable::FindValue(theMap,"myHRow").toInt();
811   myVRow = VISU::Storable::FindValue(theMap,"myVRow").toInt();
812   bool ok = false;
813   QString z_str = VISU::Storable::FindValue(theMap,"myZRow", &ok);
814   myZRow = ok ? z_str.toInt() : 0;
815
816   myColor.R = VISU::Storable::FindValue(theMap,"myColor.R").toDouble();
817   myColor.G = VISU::Storable::FindValue(theMap,"myColor.G").toDouble();
818   myColor.B = VISU::Storable::FindValue(theMap,"myColor.B").toDouble();
819   myMarker = ( VISU::Curve::MarkerType )( VISU::Storable::FindValue(theMap,"myMarker").toInt() );
820   myLine = ( VISU::Curve::LineType )( VISU::Storable::FindValue(theMap,"myLine").toInt() );
821   myLineWidth = VISU::Storable::FindValue(theMap,"myLineWidth").toInt();
822   myAuto = VISU::Storable::FindValue(theMap,"myAuto").toInt();
823   return Build( true );
824 }
825 /*!
826   Flushes curve data into stream
827 */
828 void VISU::Curve_i::ToStream( std::ostringstream& theStr )
829 {
830   Storable::DataToStream( theStr, "myName",      GetName().c_str() );
831   Storable::DataToStream( theStr, "myHRow",      myHRow );
832   Storable::DataToStream( theStr, "myVRow",      myVRow );
833   Storable::DataToStream( theStr, "myZRow",      myZRow );
834   Storable::DataToStream( theStr, "myColor.R",   myColor.R );
835   Storable::DataToStream( theStr, "myColor.G",   myColor.G );
836   Storable::DataToStream( theStr, "myColor.B",   myColor.B );
837   Storable::DataToStream( theStr, "myMarker",    myMarker );
838   Storable::DataToStream( theStr, "myLine",      myLine );
839   Storable::DataToStream( theStr, "myLineWidth", myLineWidth );
840   Storable::DataToStream( theStr, "myAuto",      myAuto );
841 }
842 /*!
843   Gets reference table's entry
844 */
845 std::string VISU::Curve_i::GetTableID() {
846   return myTable->GetObjectEntry();
847 }
848 /*!
849   Called from engine to restore curve from the file
850 */
851 VISU::Storable* VISU::Curve_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
852                                               const Storable::TRestoringMap& theMap,
853                                               const std::string& thePrefix,
854                                               CORBA::Boolean theIsMultiFile)
855 {
856   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
857   VISU::Table_i* pTable = GetTable(aStudy, theSObject->GetFather());
858   if( pTable != NULL ) {
859     VISU::Curve_i* pResent = new VISU::Curve_i( aStudy, pTable, 0, 0, 0 );
860     return pResent->Restore( theMap, theSObject);
861   }
862   return NULL;
863 }
864
865 void VISU::Curve_i::RemoveFromStudy()
866 {
867   struct TRemoveFromStudy: public SALOME_Event
868   {
869     VISU::Curve_i* myRemovable;
870     TRemoveFromStudy(VISU::Curve_i* theRemovable):
871       myRemovable(theRemovable)
872     {}
873     
874     virtual
875     void
876     Execute()
877     {
878       VISU::DeleteActors(myRemovable);
879       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
880     }
881   };
882
883   ProcessVoidEvent(new TRemoveFromStudy(this));
884 }
885
886 SALOMEDS::SObject_var VISU::Curve_i::GetSObject()
887 {
888   return mySObj;
889 }
890
891 //----------------------------------------------------------------
892 //                      Container Object
893 //----------------------------------------------------------------
894 int VISU::Container_i::myNbPresent = 0;
895 const string VISU::Container_i::myComment  = "CONTAINER";
896 /*!
897   Generate unique name
898 */
899 QString VISU::Container_i::GenerateName()
900 {
901   return VISU::GenerateName( "Plot2DView", ++myNbPresent );
902 }
903 /*!
904   Gets comment string
905 */
906 const char* VISU::Container_i::GetComment() const
907 {
908   return myComment.c_str();
909 }
910 /*!
911   Constructor
912 */
913 VISU::Container_i::Container_i( SALOMEDS::Study_ptr theStudy )
914      : PrsObject_i( theStudy )
915 {
916 }
917 /*!
918   Destructor
919 */
920 VISU::Container_i::~Container_i()
921 {
922   MESSAGE("Container_i::~Container_i");
923   myCurves.clear();
924 }
925 /*!
926   Inserts curve into the container
927 */
928 void VISU::Container_i::AddCurve( Curve_ptr theCurve )
929 {
930   if ( GetStudyDocument()->_is_nil() )
931     return;
932   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
933   if ( mySO->_is_nil() )
934     return;
935   PortableServer::POA_ptr aPOA = GetPOA();
936   Curve_i* pCurve = dynamic_cast<Curve_i*>( aPOA->reference_to_servant( theCurve ) );
937   if( pCurve ) {
938     QString entry = pCurve->GetEntry();
939     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( entry.latin1() );
940     if ( !SO->_is_nil() && myCurves.find( entry ) == myCurves.end() ) {
941       myCurves.append( entry );
942       SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
943       SALOMEDS::SObject_var newSO = Builder->NewObject( mySO );
944       Builder->Addreference( newSO, SO );
945     }
946   }
947 }
948 /*!
949   Removes curve from the container
950 */
951 void VISU::Container_i::RemoveCurve( Curve_ptr theCurve )
952 {
953   if ( GetStudyDocument()->_is_nil() )
954     return;
955   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
956   if ( mySO->_is_nil() )
957     return;
958   PortableServer::POA_ptr aPOA = GetPOA();
959   Curve_i* pCurve = dynamic_cast<Curve_i*>( aPOA->reference_to_servant( theCurve ) );
960   if( pCurve ) {
961     QString entry = pCurve->GetEntry();
962     if ( myCurves.find( entry ) != myCurves.end() ) {
963       // found !!!
964       myCurves.remove( entry );
965       SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
966       SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
967       for ( ; CI->More(); CI->Next() ) {
968         SALOMEDS::SObject_var childSO = CI->Value();
969         SALOMEDS::SObject_var refSO;
970         if ( childSO->ReferencedObject( refSO ) && !refSO->_is_nil() && entry == QString( refSO->GetID() ) ) {
971           Builder->RemoveObject( childSO );
972         }
973       }
974     }
975   }
976 }
977 /*!
978   Gets number of curves in the container
979 */
980 CORBA::Long VISU::Container_i::GetNbCurves()
981 {
982   Update();
983   return myCurves.count();
984 }
985 /*!
986   Clears container
987 */
988 void VISU::Container_i::Clear()
989 {
990   if ( GetStudyDocument()->_is_nil() )
991     return;
992   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
993   if ( mySO->_is_nil() )
994     return;
995   QStringList toDelete;
996   SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
997   for ( ; CI->More(); CI->Next() ) {
998     toDelete.append( CI->Value()->GetID() );
999   }
1000   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1001   for ( int i = 0; i < toDelete.count(); i++ ) {
1002     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( toDelete[i].latin1() );
1003     Builder->RemoveObject( SO );
1004   }
1005   myCurves.clear();
1006 }
1007 /*!
1008   Creates container object
1009 */
1010 VISU::Storable* VISU::Container_i::Create()
1011 {
1012   // generate name ...
1013   SetName(GenerateName(), false);
1014   // ... and build the object
1015   return Build( false );
1016 }
1017 /*!
1018   Builds presentation of container
1019 */
1020 VISU::Storable* VISU::Container_i::Build( int theRestoring )
1021 {
1022   if ( !theRestoring ) {
1023     // looking for component
1024     SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
1025     // create SObject and set attributes
1026     QString aComment;
1027     aComment.sprintf("myComment=%s",GetComment());
1028     string anEntry = CreateAttributes( GetStudyDocument(),
1029                                        SComponent->GetID(),
1030                                        "",
1031                                        GetID(),
1032                                        GetName(),
1033                                        "",
1034                                        aComment.latin1(),
1035                                        true );
1036     mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID(anEntry.c_str()));
1037   }
1038   return this;
1039 }
1040 /*!
1041   Updates presentation of container
1042 */
1043 void VISU::Container_i::Update()
1044 {
1045   if ( GetStudyDocument()->_is_nil() )
1046     return;
1047   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1048   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1049   SALOMEDS::GenericAttribute_var anAttr;
1050   if ( !mySO->_is_nil() ) {
1051     QStringList toDelete;
1052     int i;
1053     for ( i = 0; i < myCurves.count(); i++ ) {
1054       SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( myCurves[i].latin1() );
1055       if ( !SO->_is_nil() && Builder->FindAttribute( SO, anAttr, "AttributeIOR" ) ) {
1056         // if real Curve Object still exists
1057         SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1058         bool bFound = false;
1059         for ( ; CI->More(); CI->Next() ) {
1060           SALOMEDS::SObject_var childSO = CI->Value();
1061           SALOMEDS::SObject_var refSO;
1062           if ( childSO->ReferencedObject( refSO ) && !refSO->_is_nil() && myCurves[i] == QString( refSO->GetID() ) ) {
1063             bFound = true; break;
1064           }
1065         }
1066         if (! bFound ) {
1067           // create SObject referenced to real curve object if is not yet added
1068           SALOMEDS::SObject_var newSO = Builder->NewObject( mySO );
1069           Builder->Addreference( newSO, SO );
1070         }
1071       }
1072       else {
1073         // real Curve Object doesn't exist (might be removed)
1074         toDelete.append( myCurves[i] );
1075       }
1076     }
1077     for ( i = 0; i < toDelete.count(); i++ ) {
1078       myCurves.remove( toDelete[i] );
1079     }
1080     toDelete.clear();
1081     SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1082     for ( ; CI->More(); CI->Next() ) {
1083       SALOMEDS::SObject_var childSO = CI->Value();
1084       SALOMEDS::SObject_var refSO;
1085       if ( childSO->ReferencedObject( refSO ) && ( refSO->_is_nil() || !Builder->FindAttribute( refSO, anAttr, "AttributeIOR" ) ||
1086                                                    myCurves.find( refSO->GetID() ) == myCurves.end() ) ) {
1087         toDelete.append( childSO->GetID() );
1088       }
1089     }
1090     for ( i = 0; i < toDelete.count(); i++ ) {
1091       SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1092       for ( ; CI->More(); CI->Next() ) {
1093         SALOMEDS::SObject_var childSO = CI->Value();
1094         if ( toDelete[i] == CI->Value()->GetID() ) {
1095           Builder->RemoveObject( childSO );
1096         }
1097       }
1098     }
1099   }
1100 }
1101 /*!
1102   Gets curve from container by index
1103   NB : curves are numbered from 1
1104 */
1105 VISU::Curve_i* VISU::Container_i::GetCurve( CORBA::Long theIndex )
1106 {
1107   if ( theIndex > 0 && theIndex <= myCurves.count()  ) {
1108     SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1109     SALOMEDS::GenericAttribute_var anAttr;
1110     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( myCurves[  theIndex-1 ].latin1() );
1111     CORBA::Object_var anObject = VISU::SObjectToObject( SO );
1112     if( !CORBA::is_nil( anObject ) ) {
1113       // if real Curve Object exists
1114       CORBA::Object_ptr aCurve = VISU::Curve::_narrow( anObject );
1115       if( !CORBA::is_nil( aCurve ) )
1116       return dynamic_cast<VISU::Curve_i*>(VISU::GetServant(aCurve).in());
1117     }
1118   }
1119   return NULL;
1120 }
1121 /*!
1122   Restores container data from the stream
1123 */
1124 VISU::Storable* VISU::Container_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr SO )
1125 {
1126   if(MYDEBUG) MESSAGE(GetComment());
1127   mySObj = SALOMEDS::SObject::_duplicate(SO);
1128   SetName(VISU::Storable::FindValue( theMap, "myName" ).latin1(), false);
1129   QString val = VISU::Storable::FindValue( theMap, "myCurves" );
1130   myCurves = QStringList::split( QString( "*" ), val, false );
1131   return Build( true );
1132 }
1133 /*!
1134   Flushes container data into the stream
1135 */
1136 void VISU::Container_i::ToStream( std::ostringstream& theStr )
1137 {
1138   Storable::DataToStream( theStr, "myName",   GetName().c_str() );
1139   Storable::DataToStream( theStr, "myCurves", myCurves.join( QString( "*" ) ) );
1140 //  theStr<<" myName "<<myName;
1141 //  theStr<<" myCurves "<<myCurves.join( QString( "*" ) ).latin1()<<"* ";
1142 }
1143 /*!
1144   Called from engine to restore container from the file
1145 */
1146 VISU::Storable* VISU::Container_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
1147                                                   const Storable::TRestoringMap& theMap,
1148                                                   const std::string& thePrefix,
1149                                                   CORBA::Boolean theIsMultiFile)
1150 {
1151   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
1152   VISU::Container_i* pResent = new VISU::Container_i( aStudy );
1153   return pResent->Restore( theMap, theSObject );
1154 }
1155
1156 void VISU::Container_i::RemoveFromStudy()
1157 {
1158   struct TRemoveFromStudy: public SALOME_Event
1159   {
1160     VISU::Container_i* myRemovable;
1161     TRemoveFromStudy(VISU::Container_i* theRemovable):
1162       myRemovable(theRemovable)
1163     {}
1164     
1165     virtual
1166     void
1167     Execute()
1168     {
1169       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
1170     }
1171   };
1172
1173   ProcessVoidEvent(new TRemoveFromStudy(this));
1174 }
1175
1176 SALOMEDS::SObject_var VISU::Container_i::GetSObject()
1177 {
1178   return mySObj;
1179 }
1180
1181 //-------------------------------------------------------------
1182 //             Implementation of reading from file
1183 //-------------------------------------------------------------
1184 typedef string TValue;
1185 typedef vector<TValue> TValues;
1186
1187 struct TRow{
1188   string myTitle;
1189   string myUnit;
1190   TValues myValues;
1191 };
1192
1193 typedef vector<TRow> TRows;
1194
1195 struct TTable2D {
1196   string myTitle;
1197   vector<string> myColumnUnits;
1198   vector<string> myColumnTitles;
1199   TRows myRows;
1200   int Check(){
1201     if(myRows.empty()) return 0;
1202     int iEnd = myRows[0].myValues.size();
1203     if(iEnd == 0) return 0;
1204     if(myColumnTitles.size() != iEnd) myColumnTitles.resize(iEnd);
1205     if(myColumnUnits.size() != iEnd) myColumnUnits.resize(iEnd);
1206     int jEnd = myRows.size();
1207     for(int j = 0; j < jEnd; j++)
1208       if(myRows[j].myValues.size() != iEnd)
1209         return 0;
1210     return 1;
1211   }
1212   void getColumns(TTable2D& theTable2D) const {
1213     TRows& aRows = theTable2D.myRows;
1214     aRows.clear();
1215     if(myRows.empty()) return;
1216     int jEnd = myRows.size();
1217     //Define Titles & Units
1218     theTable2D.myColumnTitles.resize(jEnd);
1219     theTable2D.myColumnUnits.resize(jEnd);
1220     for(int j = 0; j < jEnd; j++){
1221       theTable2D.myColumnTitles[j] = myRows[j].myTitle;
1222       theTable2D.myColumnUnits[j] = myRows[j].myUnit;
1223     }
1224     //Define Rows
1225     int iEnd = myRows[0].myValues.size();
1226     for(int i = 0; i < iEnd; i++){
1227       TRow aNewRow;
1228       aNewRow.myTitle = myColumnTitles[i];
1229       aNewRow.myUnit = myColumnUnits[i];
1230       aNewRow.myValues.resize(jEnd);
1231       for(int j = 0; j < jEnd; j++){
1232         aNewRow.myValues[j] = myRows[j].myValues[i];
1233       }
1234       aRows.push_back(aNewRow);
1235     }
1236   }
1237 };
1238
1239 typedef vector<TTable2D> TTableCont;
1240
1241 int getLine(ifstream& theStmIn, QString& theString){
1242   char tmp;
1243   ostrstream aStrOut;
1244   while(theStmIn.get(tmp)){
1245     aStrOut<<tmp;
1246     if(tmp == '\n') break;
1247   }
1248   aStrOut<<ends;
1249   theString = aStrOut.str();
1250   return !theStmIn.eof();
1251 }
1252
1253 void ImportTables(const char* theFileName, TTableCont& theTableCont){
1254   ifstream aStmIn;
1255   QFileInfo aFileInfo( theFileName );
1256   if( !aFileInfo.isFile() || !aFileInfo.isReadable() || !aFileInfo.size() )
1257     return;
1258   aStmIn.open( theFileName );
1259   QString aTmp;
1260   do {
1261     // find beginning of table (tables are separated by empty lines)
1262     while( getLine( aStmIn, aTmp ) && aTmp.stripWhiteSpace() == "");
1263     TTable2D aTable2D;
1264     if(MYDEBUG) cout << "New table is found" << endl;
1265     while( !aStmIn.eof() && aTmp.stripWhiteSpace() != "" ){
1266       QString data = aTmp.stripWhiteSpace();
1267       QString cmt = "";
1268       QString keyword = "";
1269       // split string to data and comment (comment starts from '#' symbol)
1270       int index = aTmp.find( "#" );
1271       if ( index >= 0 ) {
1272         data = aTmp.left( index ).stripWhiteSpace();
1273         cmt = aTmp.mid( index+1 ).stripWhiteSpace();
1274       }
1275       // if comment is not empty, try to get keyword from it (separated by ':' symbol)
1276       if ( !cmt.isEmpty() ) {
1277         int index1 = cmt.find( ":" );
1278         if ( index1 >= 0 ) {
1279           QString tmpstr = cmt.left( index1 ).stripWhiteSpace();
1280           if ( tmpstr == QString( "TITLE" ) ||
1281                tmpstr == QString( "COLUMN_TITLES" ) ||
1282                tmpstr == QString( "COLUMN_UNITS" ) ||
1283                tmpstr == QString( "COMMENT" ) ) {
1284             keyword = tmpstr;
1285             cmt = cmt.mid( index1+1 ).stripWhiteSpace();
1286           }
1287         }
1288       }
1289       // if data is empty, process only comment
1290       if ( data.isEmpty() ) {
1291         // if keyword is found, try to process it
1292         // elsewise it is a simple comment, just ignore it
1293         if ( !keyword.isEmpty() ) {
1294           if ( keyword == QString( "TITLE" ) ) {
1295             QString title = cmt;
1296             if ( aTable2D.myTitle != "" )
1297               title = QString( aTable2D.myTitle.c_str() ) + QString( " " ) + title;
1298             if(MYDEBUG) cout << "...Table TITLE is: " << title.latin1() << endl;
1299             aTable2D.myTitle = title.latin1();
1300           }
1301           else if ( keyword == QString( "COLUMN_TITLES" ) ) {
1302             // comment may contain column headers
1303             QStringList aStrList = QStringList::split( "|", cmt );
1304             if(MYDEBUG) cout << "...Column TITLES are: ";
1305             for ( int i = 0; i < aStrList.count(); i++ ) {
1306               QString tmpstr = aStrList[ i ].stripWhiteSpace();
1307               if(MYDEBUG) cout << tmpstr.latin1() << " ";
1308               aTable2D.myColumnTitles.push_back( tmpstr.latin1() );
1309             }
1310             if(MYDEBUG) cout << endl;
1311           }
1312           else if ( keyword == QString( "COLUMN_UNITS" ) ) {
1313             // comment may contain column units
1314             QStringList aStrList = QStringList::split( " ", cmt );
1315             if(MYDEBUG) cout << "...Column UNITS are: ";
1316             for ( int i = 0; i < aStrList.count(); i++ ) {
1317               QString tmpstr = aStrList[ i ].stripWhiteSpace();
1318               if(MYDEBUG) cout << tmpstr.latin1() << " ";
1319               aTable2D.myColumnUnits.push_back( tmpstr.latin1() );
1320             }
1321             if(MYDEBUG) cout << endl;
1322           }
1323           else if ( keyword == QString( "COMMENT" ) ) {
1324             // keyword 'COMMENT' processing can be here
1325             // currently it is ignored
1326             if(MYDEBUG) cout << "...COMMENT: " << cmt.latin1() << endl;
1327           }
1328         }
1329         else {
1330           if(MYDEBUG) cout << "...comment: " << cmt.latin1() << endl;
1331           // simple comment processing can be here
1332           // currently it is ignored
1333         }
1334       }
1335       // if data is not empty, try to process it
1336       else {
1337         TRow aRow;
1338         if(MYDEBUG) cout << "...New row is found: " << endl;
1339         if ( !cmt.isEmpty() ) {
1340           aRow.myTitle = cmt.latin1();
1341           if(MYDEBUG) cout << "......ROW TITLE is: " << cmt.latin1() << endl;
1342         }
1343         QString datar1 = data.replace(QRegExp("\t"), " ");
1344         QStringList aValList = QStringList::split( " ", datar1 );
1345         for ( int i = 0; i < aValList.count(); i++ ) {
1346           if ( aValList[i].stripWhiteSpace() != "" ) {
1347             TValue aVal = aValList[i].stripWhiteSpace().latin1();
1348             aRow.myValues.push_back( aVal );
1349           }
1350         }
1351         if( aRow.myValues.size() > 0 )
1352           aTable2D.myRows.push_back( aRow );
1353         // ************** OLD CODE ******************
1354         /*
1355         TValue aVal;
1356         istrstream aStream( data );
1357         aStream.precision( STRPRECISION );
1358         while( aStream >> aVal ) {
1359           aRow.myValues.push_back( aVal );
1360         }
1361         if( aRow.myValues.size() > 0 )
1362           aTable2D.myRows.push_back( aRow );
1363         */
1364         // ************** OLD CODE ******************
1365       }
1366       getLine( aStmIn, aTmp );
1367     }
1368     if( aTable2D.Check() ) {
1369       if(MYDEBUG) cout << "aTable2D is checked OK " << aTable2D.myTitle << endl;
1370       theTableCont.push_back( aTable2D );
1371     }
1372   }
1373   while( !aStmIn.eof() );
1374   aStmIn.close();
1375   if(MYDEBUG) cout << "After close" << endl;
1376 }
1377
1378 SALOMEDS::SObject_var VISU::ImportTables(const char* theFileName, SALOMEDS::Study_ptr theStudy){
1379   TTableCont aTableCont;
1380   ImportTables(theFileName,aTableCont);
1381   if(aTableCont.empty()) return SALOMEDS::SObject::_nil();
1382   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
1383   SALOMEDS::SComponent_var theSComponent = VISU::FindOrCreateVisuComponent(theStudy);
1384   SALOMEDS::SObject_var aFileObject = aStudyBuilder->NewObject(theSComponent);
1385   SALOMEDS::GenericAttribute_var anAttr =
1386     aStudyBuilder->FindOrCreateAttribute(aFileObject, "AttributeName");
1387   SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
1388   QFileInfo aFileInfo(theFileName);
1389   aName->SetValue(aFileInfo.fileName().latin1());
1390   anAttr = aStudyBuilder->FindOrCreateAttribute(aFileObject, "AttributeString");
1391   SALOMEDS::AttributeString_var aComment = SALOMEDS::AttributeString::_narrow(anAttr);
1392   QString aString;
1393   aString.sprintf("myComment=ImportTables;myFileName=%s",
1394                   aFileInfo.absFilePath().latin1());
1395   aComment->SetValue(aString.latin1());
1396   for(int i = 0, iEnd = aTableCont.size(); i < iEnd; i++){
1397     const TTable2D& aTable2D = aTableCont[i];
1398     SALOMEDS::SObject_var aRealObject = aStudyBuilder->NewObject(aFileObject);
1399     anAttr = aStudyBuilder->FindOrCreateAttribute(aRealObject, "AttributeName");
1400     aName = SALOMEDS::AttributeName::_narrow(anAttr);
1401     if(MYDEBUG) cout<<"aTable2D.myTitle = "<<aTable2D.myTitle<<endl;
1402     if(aTable2D.myTitle != "")
1403       aName->SetValue(aTable2D.myTitle.c_str());
1404     else{
1405       QString aNewName;
1406       aNewName.sprintf("Table:%d",i);
1407       aName->SetValue(aNewName.latin1());
1408     }
1409     anAttr = aStudyBuilder->FindOrCreateAttribute(aRealObject, "AttributeTableOfReal");
1410     SALOMEDS::AttributeTableOfReal_var aTableOfReal = SALOMEDS::AttributeTableOfReal::_narrow(anAttr);
1411     aTableOfReal->SetTitle(aTable2D.myTitle.c_str());
1412     TTable2D aNewTable2D;
1413     aTable2D.getColumns(aNewTable2D);
1414     int kEnd = aNewTable2D.myRows[0].myValues.size();
1415     aTableOfReal->SetNbColumns(kEnd);
1416     for(int j = 0, jEnd = aNewTable2D.myRows.size(); j < jEnd; j++){
1417       if(MYDEBUG) cout<<"j = "<<j<<"; kEnd = "<<kEnd<<endl;
1418
1419       for(int k = 0; k < kEnd; k++){
1420         QString aVal = aNewTable2D.myRows[j].myValues[k].c_str();
1421         bool anIsOk = false;
1422         double aValue = aVal.toDouble(&anIsOk);
1423         if(anIsOk && !aVal.contains("NAN",false) && !aVal.contains("INF",false))
1424           aTableOfReal->PutValue(aValue,j+1,k+1);
1425       }
1426
1427       aTableOfReal->SetRowTitle(j+1,aNewTable2D.myRows[j].myTitle.c_str());
1428       aTableOfReal->SetRowUnit(j+1,aNewTable2D.myRows[j].myUnit.c_str());
1429     }
1430     for(int k = 0; k < kEnd; k++)
1431       aTableOfReal->SetColumnTitle(k+1,aNewTable2D.myColumnTitles[k].c_str());
1432   }
1433   return aFileObject;
1434 }
1435
1436 template<class TTableAttr> bool ExportTableToFile(const TTableAttr& aTabAttr,
1437                                                   const char* theFileName)
1438 {
1439   if (!CORBA::is_nil(aTabAttr)) {
1440     QFile aFile(theFileName);
1441     aFile.open(IO_WriteOnly);
1442
1443     /* extract the tabe info and write it into file */
1444
1445     QString aTitle(aTabAttr->GetTitle()); /*Table title*/
1446     int aRowsNb = aTabAttr->GetNbRows();
1447     int aColNb  = aTabAttr->GetNbColumns();
1448
1449     SALOMEDS::StringSeq_var aRowTitles = aTabAttr->GetRowTitles();
1450     QString anAbscissTitle(aRowTitles[0]); /*Absciss row title (X coord)*/
1451     anAbscissTitle.stripWhiteSpace();
1452
1453     SALOMEDS::StringSeq_var aRowUnits = aTabAttr->GetRowUnits();
1454     QString anAbscissUnit(aRowUnits[0]);
1455     anAbscissUnit.stripWhiteSpace();
1456
1457     SALOMEDS::StringSeq_var aColumnTitles = aTabAttr->GetColumnTitles();
1458     if (aRowsNb > 2 && aTitle.length() )  aTitle = aTitle + " - ";
1459
1460     QString aLine;
1461     for (int i = 2; i <= aRowsNb; i++ )
1462       {
1463         /* TITLE */
1464         QString anOrdinate(aRowTitles[i-1]), aTail;
1465         anOrdinate.stripWhiteSpace();
1466
1467         aLine = "#TITLE: " + aTitle +
1468           ((anOrdinate.length())?  anOrdinate :
1469                                   (aRowsNb>2)? aTail.sprintf("%d",i-1) : aTail.sprintf("") ) + "\n";
1470         aFile.writeBlock(aLine, aLine.length() );
1471
1472         /* COLUMN_TITLES */
1473         if ( anAbscissTitle.length() || anOrdinate.length() ) {
1474           aLine = "#COLUMN_TITLES: " + anAbscissTitle + " | " + anOrdinate + "\n";
1475           aFile.writeBlock(aLine, aLine.length() );
1476         }
1477
1478         /* COLUMN_UNITS */
1479         aLine = anAbscissUnit + " " +aRowUnits[i-1];
1480         if (!aLine.stripWhiteSpace().isEmpty()) {
1481           aLine = "#COLUMN_UNITS: " + aLine  + "\n";
1482           aFile.writeBlock(aLine, aLine.length() );
1483         }
1484
1485         /* CURVE COORDINATES */
1486         for (int j = 1; j <= aColNb; j++)
1487           {
1488             if ( aTabAttr -> HasValue(i,j) &&  aTabAttr -> HasValue(1, j)) {
1489               aLine = aLine.sprintf("%.16g %.16g",
1490                                     (double)(aTabAttr->GetValue(1,j)),
1491                                     (double)(aTabAttr->GetValue(i,j)));  /* aTabAttr->GetValue(1,j) - X coord */
1492               if ( !aLine.stripWhiteSpace().isEmpty() ) {
1493                 QString aColTitle(aColumnTitles[j-1]);
1494                 if ( !aColTitle.stripWhiteSpace().isEmpty() )
1495                   aLine = aLine + "  #TITLE: " + aColTitle ;
1496                 aFile.writeBlock(aLine + "\n", aLine.length() + 1);
1497               }
1498             }
1499           }
1500         aFile.writeBlock("\n", 1);
1501       }
1502     aFile.close();
1503     return true;
1504   }
1505   return false;
1506 }
1507
1508 bool VISU::ExportTableToFile(SALOMEDS::SObject_ptr theTable, const char* theFileName)
1509 {
1510   //Find table
1511   SALOMEDS::GenericAttribute_var anAttr ;
1512   if (theTable->FindAttribute(anAttr, "AttributeTableOfReal"))
1513     {
1514       SALOMEDS::AttributeTableOfReal_var aTabAttr = SALOMEDS::AttributeTableOfReal ::_narrow(anAttr);
1515       return ExportTableToFile ( aTabAttr , theFileName);
1516
1517     }
1518   else if (theTable->FindAttribute(anAttr, "AttributeTableOfInteger")) {
1519
1520     SALOMEDS::AttributeTableOfInteger_var aTabAttr = SALOMEDS::AttributeTableOfInteger ::_narrow(anAttr);
1521     return ExportTableToFile ( aTabAttr , theFileName);
1522
1523   }
1524   return false;
1525 }