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