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