Salome HOME
Implementation of the "21384: [CEA 508] Plot2d Allow user to rescale curve" isuue.
[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   myScale = 1.0;
524 }
525 /*!
526   Destructor
527 */
528 VISU::Curve_i::~Curve_i()
529 {
530   MESSAGE("Curve_i::~Curve_i");
531 }
532
533 //----------------------------------------------------------------------------
534 void
535 VISU::Curve_i
536 ::SetTitle( const char* theTitle )
537 {
538   SetName( theTitle, true );
539 }
540
541 //----------------------------------------------------------------------------
542 char*
543 VISU::Curve_i
544 ::GetTitle()
545 {
546   return CORBA::string_dup( GetName().c_str() );
547 }
548
549 //----------------------------------------------------------------------------
550 void
551 VISU::Curve_i
552 ::SetColor( const SALOMEDS::Color& theColor )
553 {
554   myColor = theColor; 
555   myAuto = false;
556 }
557
558 //----------------------------------------------------------------------------
559 SALOMEDS::Color
560 VISU::Curve_i
561 ::GetColor()
562 {
563   return myColor;
564 }
565
566 //----------------------------------------------------------------------------
567 void
568 VISU::Curve_i
569 ::SetMarker( VISU::Curve::MarkerType theType )
570 {
571   myMarker = theType; 
572   myAuto = false;
573 }
574
575 //----------------------------------------------------------------------------
576 VISU::Curve::MarkerType
577 VISU::Curve_i
578 ::GetMarker()
579 {
580   return myMarker;
581 }
582
583 //----------------------------------------------------------------------------
584 void
585 VISU::Curve_i
586 ::SetLine( VISU::Curve::LineType theType, CORBA::Long theWidth )
587 {
588   myLine = theType; 
589   myLineWidth = theWidth; 
590   myAuto = false;
591 }
592
593 //----------------------------------------------------------------------------
594 VISU::Curve::LineType
595 VISU::Curve_i
596 ::GetLine()
597 {
598   return myLine;
599 }
600
601 //----------------------------------------------------------------------------
602 CORBA::Long
603 VISU::Curve_i
604 ::GetLineWidth()
605 {
606   return myLineWidth;
607 }
608
609 //----------------------------------------------------------------------------
610 void 
611 VISU::Curve_i
612 ::SetScale( CORBA::Double theCoef )
613 {
614   myScale = theCoef;  
615   UpdatePlot2d( this, eUpdateData );
616 }
617
618 //----------------------------------------------------------------------------
619 CORBA::Double 
620 VISU::Curve_i
621 ::GetScale()
622 {
623   return myScale;    
624 }
625
626 //----------------------------------------------------------------------------
627 void 
628 VISU::Curve_i
629 ::RemoveScale()
630 {
631   SetScale( 1.0 );
632 }
633
634 //----------------------------------------------------------------------------
635 /*!
636   Creates curve object
637 */
638 VISU::Storable* VISU::Curve_i::Create()
639 {
640   // generate name ...
641   SetName(GetVerTitle(), false);
642   if ( GetName() == "" )
643     SetName(GenerateName().toLatin1().data(), false);
644   // ... and build the object
645   return Build( false );
646 }
647 /*!
648   Builds presentation of curve
649 */
650 VISU::Storable* VISU::Curve_i::Build(int theRestoring )
651 {
652   if ( myTable != NULL ) {
653     // getting table SObject by it's entry
654     int nbRows = myTable->GetNbRows();
655     if ( myHRow > 0 && myHRow <= nbRows && myVRow > 0 && myVRow <= nbRows ) {
656       if ( !theRestoring ) {
657         // look for component
658         SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
659         // create SObject and set attributes
660         QString aComment;
661         aComment.sprintf("myComment=%s",GetComment());
662         string anEntry = CreateAttributes( GetStudyDocument(),
663                                           myTable->GetObjectEntry(),
664                                           "",
665                                           GetID(),
666                                           GetName(),
667                                           "",
668                                           aComment.toLatin1().data(),
669                                           true );
670         // create SObject referenced to real table object
671         mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID(anEntry.c_str()));
672
673         // Set icon
674         SALOMEDS::StudyBuilder_var aStudyBuilder = GetStudyDocument()->NewBuilder();
675         SALOMEDS::GenericAttribute_var anAttr;
676         SALOMEDS::AttributePixMap_var  aPixmap;
677         anAttr  = aStudyBuilder->FindOrCreateAttribute( mySObj, "AttributePixMap" );
678         aPixmap = SALOMEDS::AttributePixMap::_narrow( anAttr );
679         aPixmap ->SetPixMap("ICON_TREE_CURVE");
680       }
681       return this;
682     }
683   }
684   return NULL;
685 }
686
687 /*!
688   Returns CORBA::True if curve refers to valid table data
689 */
690 CORBA::Boolean VISU::Curve_i::IsValid()
691 {
692   // getting table SObject by it's entry
693   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
694   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
695   SALOMEDS::GenericAttribute_var        anAttr;
696   SALOMEDS::AttributeTableOfInteger_var anInt;
697   SALOMEDS::AttributeTableOfReal_var    aReal;
698   if ( !SO->_is_nil() ) {
699     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
700       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
701       if ( myHRow > 0 && myHRow <= anInt->GetNbRows() && myVRow > 0 && myVRow <= anInt->GetNbRows() ) {
702         return true;
703       }
704     }
705     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
706       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
707       if ( myHRow > 0 && myHRow <= aReal->GetNbRows() && myVRow > 0 && myVRow <= aReal->GetNbRows() ) {
708         return true;
709       }
710     }
711   }
712   return false;
713 }
714 /*!
715   Returns hor.axis title
716 */
717 string VISU::Curve_i::GetHorTitle()
718 {
719   string title;
720   // getting table SObject by it's entry
721   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
722   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
723   SALOMEDS::GenericAttribute_var        anAttr;
724   SALOMEDS::AttributeTableOfInteger_var anInt;
725   SALOMEDS::AttributeTableOfReal_var    aReal;
726   if ( !SO->_is_nil() ) {
727     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
728       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
729       SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
730       if ( rowTitles->length() > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() ) {
731         title = rowTitles[ myHRow-1 ];
732       }
733     }
734     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
735       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
736       SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
737       if ( rowTitles->length() > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() ) {
738         title = rowTitles[ myHRow-1 ];
739       }
740     }
741   }
742   return title;
743 }
744 /*!
745   Returns ver.axis title
746 */
747 string VISU::Curve_i::GetVerTitle()
748 {
749   string title;
750   // getting table SObject by it's entry
751   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
752   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
753   SALOMEDS::GenericAttribute_var        anAttr;
754   SALOMEDS::AttributeTableOfInteger_var anInt;
755   SALOMEDS::AttributeTableOfReal_var    aReal;
756   if ( !SO->_is_nil() ) {
757     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
758       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
759       SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
760       if ( rowTitles->length() > 0 && myVRow > 0 && myVRow <= anInt->GetNbRows() )
761         title = rowTitles[ myVRow-1 ];
762     }
763     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
764       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
765       SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
766       if ( rowTitles->length() > 0 && myVRow > 0 && myVRow <= aReal->GetNbRows() )
767         title = rowTitles[ myVRow-1 ];
768     }
769   }
770   return title;
771 }
772 /*!
773   Returns hor.axis units
774 */
775 string VISU::Curve_i::GetHorUnits()
776 {
777   string units;
778   // getting table SObject by it's entry
779   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
780   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
781   SALOMEDS::GenericAttribute_var        anAttr;
782   SALOMEDS::AttributeTableOfInteger_var anInt;
783   SALOMEDS::AttributeTableOfReal_var    aReal;
784   if ( !SO->_is_nil()  ) {
785     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
786       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
787       SALOMEDS::StringSeq_var rowUnits = anInt->GetRowUnits();
788       if ( rowUnits->length() > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() )
789         units = rowUnits[ myHRow-1 ];
790     }
791     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
792       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
793       SALOMEDS::StringSeq_var rowUnits = aReal->GetRowUnits();
794       if ( rowUnits->length() > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() )
795         units = rowUnits[ myHRow-1 ];
796     }
797   }
798   return units;
799 }
800 /*!
801   Returns ver.axis units
802 */
803 string VISU::Curve_i::GetVerUnits()
804 {
805   string units;
806   // getting table SObject by it's entry
807   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
808   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
809   SALOMEDS::GenericAttribute_var        anAttr;
810   SALOMEDS::AttributeTableOfInteger_var anInt;
811   SALOMEDS::AttributeTableOfReal_var    aReal;
812   if ( !SO->_is_nil() ) {
813     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
814       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
815       SALOMEDS::StringSeq_var rowUnits = anInt->GetRowUnits();
816       if ( rowUnits->length() > 0 && myVRow > 0 && myVRow <= anInt->GetNbRows() )
817         units = rowUnits[ myVRow-1];
818     }
819     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
820       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
821       SALOMEDS::StringSeq_var rowUnits = aReal->GetRowUnits();
822       if ( rowUnits->length() > 0 && myVRow > 0 && myVRow <= aReal->GetNbRows() )
823         units = rowUnits[ myVRow-1 ];
824     }
825   }
826   return units;
827 }
828 /*!
829   Gets curve data
830 */
831 int VISU::Curve_i::GetData( double*& theHorList, double*& theVerList, QStringList& zList )
832 {
833   theHorList = 0; theVerList = 0;
834   // getting table SObject by it's entry
835   SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myTable->GetObjectEntry().c_str());
836   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
837   SALOMEDS::GenericAttribute_var        anAttr;
838   SALOMEDS::AttributeTableOfInteger_var anInt;
839   SALOMEDS::AttributeTableOfReal_var    aReal;
840
841   QString tip = "%1: %2", z_data;
842
843   if ( !SO->_is_nil() ) {
844     if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfInteger" ) ) {
845       anInt = SALOMEDS::AttributeTableOfInteger::_narrow( anAttr );
846       int nbCols = anInt->GetNbColumns(), nbRows = anInt->GetNbRows();
847       if ( nbCols > 0 && myHRow > 0 && myHRow <= anInt->GetNbRows() && myVRow > 0 && myVRow <= anInt->GetNbRows() ) {
848         int nbPoints = 0;
849         for ( int j = 1; j <= nbCols; j++ ) {
850           if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) )
851             nbPoints++;
852         }
853         if ( nbPoints > 0 ) {
854           theHorList = new double[ nbPoints ];
855           theVerList = new double[ nbPoints ];
856           int k = 0;
857
858           SALOMEDS::StringSeq_var rowTitles = anInt->GetRowTitles();
859
860           for ( int j = 1; j <= nbCols; j++ ) {
861             if ( anInt->HasValue( myHRow, j ) && anInt->HasValue( myVRow, j ) ) {
862               theHorList[k] = anInt->GetValue( myHRow, j );
863               theVerList[k] = anInt->GetValue( myVRow, j );
864
865               z_data = tip.arg( GetHorTitle().c_str() ).arg( theHorList[k] ) + "\n";
866               z_data += tip.arg( GetVerTitle().c_str() ).arg( theVerList[k] );
867
868               if( myZRow>0 && myZRow<=nbRows && anInt->HasValue( myZRow, j ) )
869               {
870                 string title;
871                 title = rowTitles[ myZRow-1 ];
872                 z_data += "\n" + tip.arg( title.c_str() ).arg( anInt->GetValue( myZRow, j ) );
873               }
874               zList.append( z_data );
875               k++;
876             }
877           }
878         }
879         return nbPoints;
880       }
881     }
882     else if ( Builder->FindAttribute( SO, anAttr, "AttributeTableOfReal" ) ) {
883       aReal = SALOMEDS::AttributeTableOfReal::_narrow( anAttr );
884       int nbCols = aReal->GetNbColumns(), nbRows = aReal->GetNbRows();
885       if ( nbCols > 0 && myHRow > 0 && myHRow <= aReal->GetNbRows() && myVRow > 0 && myVRow <= aReal->GetNbRows() ) {
886         int nbPoints = 0;
887         for ( int j = 1; j <= nbCols; j++ ) {
888           if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) )
889             nbPoints++;
890         }
891         if ( nbPoints > 0 ) {
892           theHorList = new double[ nbPoints ];
893           theVerList = new double[ nbPoints ];
894           int k = 0;
895
896           SALOMEDS::StringSeq_var rowTitles = aReal->GetRowTitles();
897
898           for ( int j = 1; j <= nbCols; j++ ) {
899             if ( aReal->HasValue( myHRow, j ) && aReal->HasValue( myVRow, j ) ) {
900               theHorList[k] = aReal->GetValue( myHRow, j );
901               theVerList[k] = aReal->GetValue( myVRow, j );
902
903               z_data = tip.arg( GetHorTitle().c_str() ).arg( theHorList[k] ) + "\n";
904               z_data += tip.arg( GetVerTitle().c_str() ).arg( theVerList[k] );
905
906               if( myZRow>0 && myZRow<=nbRows && aReal->HasValue( myZRow, j ) )
907               {
908                 string title;
909                 title = rowTitles[ myZRow-1 ];
910                 z_data += "\n" + tip.arg( title.c_str() ).arg( aReal->GetValue( myZRow, j ) );
911               }
912               zList.append( z_data );
913               k++;
914             }
915           }
916         }
917         return nbPoints;
918       }
919     }
920   }
921   return 0;
922 }
923 /*!
924   Creates curve Plot2d presentation object
925 */
926 SPlot2d_Curve* VISU::Curve_i::CreatePresentation()
927 {
928   SPlot2d_Curve* crv = new SPlot2d_Curve();
929   crv->setYAxis( myIsV2 ? QwtPlot::yRight : QwtPlot::yLeft );
930   crv->setHorTitle( GetHorTitle().c_str() );
931   string tlt = GetTitle();
932   if ( tlt.length() <= 0 )
933     tlt = GetVerTitle();
934   //crv->setVerTitle( strdup( GetVerTitle().c_str() ) );
935   //crv->setVerTitle( strdup( GetName() ) );
936   crv->setVerTitle( tlt.c_str() );
937   crv->setHorUnits( GetHorUnits().c_str() );
938   crv->setVerUnits( GetVerUnits().c_str() );
939   double* xList = 0;
940   double* yList = 0;
941   QStringList zList;
942   int     nbPoints = GetData( xList, yList, zList );
943   if ( nbPoints > 0 && xList && yList ) {
944     crv->setData( xList, yList, nbPoints, zList );
945   }
946   //cout << "********** Number of points: " << nbPoints <<endl;
947   //for ( int i =0 ; i < nbPoints; i++ ) {
948   //  cout << i<<"\t"<<xList[i] << "\t"<< yList[i] << endl;
949   //}
950   crv->setLine( (Plot2d::LineType)GetLine(), GetLineWidth() );
951   crv->setMarker( (Plot2d::MarkerType)GetMarker() );
952   SALOMEDS::Color color = GetColor();
953   crv->setColor( QColor( (int)(color.R*255.), (int)(color.G*255.), (int)(color.B*255.) ) );
954   crv->setAutoAssign( IsAuto() );
955   CORBA::String_var aString = mySObj->GetID();
956   crv->setIO(new SALOME_InteractiveObject(aString.in(), "VISU", GetName().c_str()));
957   if ( myTable )
958     crv->setTableIO(new SALOME_InteractiveObject(myTable->GetObjectEntry().c_str(), "VISU", myTable->GetName().c_str()));
959
960   if(!myContainers.isEmpty())     
961     crv->addOwners(myContainers);
962   return crv;
963 }
964 /*!
965   Restores curve object from stream
966 */
967 VISU::Storable* VISU::Curve_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr theSO)
968 {
969   if(MYDEBUG) MESSAGE(GetComment());
970   mySObj = SALOMEDS::SObject::_duplicate(theSO);
971   SetName(VISU::Storable::FindValue(theMap,"myName").toLatin1().data(), false);
972   myHRow = VISU::Storable::FindValue(theMap,"myHRow").toInt();
973   myVRow = VISU::Storable::FindValue(theMap,"myVRow").toInt();
974   bool ok = false;
975   QString z_str = VISU::Storable::FindValue(theMap,"myZRow", &ok);
976   myZRow = ok ? z_str.toInt() : 0;
977   ok = false;
978   QString v2_str = VISU::Storable::FindValue(theMap,"myIsV2", &ok);
979   myIsV2 = ok ? v2_str.toInt() : false;
980
981   QString scale_str = VISU::Storable::FindValue(theMap,"myScale", &ok);
982   myScale = ok ? scale_str.toDouble() : 1.0;
983   myColor.R = VISU::Storable::FindValue(theMap,"myColor.R").toDouble();
984   myColor.G = VISU::Storable::FindValue(theMap,"myColor.G").toDouble();
985   myColor.B = VISU::Storable::FindValue(theMap,"myColor.B").toDouble();
986   myMarker = ( VISU::Curve::MarkerType )( VISU::Storable::FindValue(theMap,"myMarker").toInt() );
987   myLine = ( VISU::Curve::LineType )( VISU::Storable::FindValue(theMap,"myLine").toInt() );
988   myLineWidth = VISU::Storable::FindValue(theMap,"myLineWidth").toInt();
989   myAuto = VISU::Storable::FindValue(theMap,"myAuto").toInt();
990   return Build( true );
991 }
992 /*!
993   Flushes curve data into stream
994 */
995 void VISU::Curve_i::ToStream( std::ostringstream& theStr )
996 {
997   Storable::DataToStream( theStr, "myName",      GetName().c_str() );
998   Storable::DataToStream( theStr, "myHRow",      myHRow );
999   Storable::DataToStream( theStr, "myVRow",      myVRow );
1000   Storable::DataToStream( theStr, "myZRow",      myZRow );
1001   Storable::DataToStream( theStr, "myIsV2",      myIsV2 );
1002   Storable::DataToStream( theStr, "myScale",     myScale );
1003   Storable::DataToStream( theStr, "myColor.R",   myColor.R );
1004   Storable::DataToStream( theStr, "myColor.G",   myColor.G );
1005   Storable::DataToStream( theStr, "myColor.B",   myColor.B );
1006   Storable::DataToStream( theStr, "myMarker",    myMarker );
1007   Storable::DataToStream( theStr, "myLine",      myLine );
1008   Storable::DataToStream( theStr, "myLineWidth", myLineWidth );
1009   Storable::DataToStream( theStr, "myAuto",      myAuto );
1010 }
1011 /*!
1012   Gets reference table's entry
1013 */
1014 std::string VISU::Curve_i::GetTableID() {
1015   return myTable->GetObjectEntry();
1016 }
1017 /*!
1018   Called from engine to restore curve from the file
1019 */
1020 VISU::Storable* VISU::Curve_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
1021                                               const Storable::TRestoringMap& theMap,
1022                                               const std::string& thePrefix,
1023                                               CORBA::Boolean theIsMultiFile)
1024 {
1025   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
1026   VISU::Table_i* pTable = GetTable(aStudy, theSObject->GetFather());
1027   if( pTable != NULL ) {
1028     VISU::Curve_i* pResent = new VISU::Curve_i( aStudy, pTable, 0, 0, 0, false );
1029     return pResent->Restore( theMap, theSObject);
1030   }
1031   return NULL;
1032 }
1033
1034 void VISU::Curve_i::RemoveFromStudy()
1035 {
1036   
1037   //remove curve from containers
1038   PortableServer::POA_ptr aPOA = GetPOA();
1039   ContainerSet::ConstIterator it = myContainers.begin();
1040   for ( ; it != myContainers.end(); it++ ) {    
1041     SALOMEDS::SObject_var aSObject =  GetStudyDocument()->FindObjectID( (*it).toLatin1().data() );
1042     if ( aSObject->_is_nil() ) continue;
1043     
1044     CORBA::Object_var anObj = VISU::SObjectToObject( aSObject );
1045     if ( CORBA::is_nil( anObj ) ) continue;
1046     VISU::Container_i* aContainer = dynamic_cast<VISU::Container_i*>( VISU::GetServant( anObj.in() ).in() );
1047     if ( !aContainer ) continue;
1048     aContainer->RemoveCurve(VISU::Curve::_narrow(aPOA->servant_to_reference(this)));
1049   }
1050
1051   struct TRemoveFromStudy: public SALOME_Event
1052   {
1053     VISU::Curve_i* myRemovable;
1054     TRemoveFromStudy(VISU::Curve_i* theRemovable):
1055       myRemovable(theRemovable)
1056     {}
1057     
1058     virtual
1059     void
1060     Execute()
1061     {
1062       VISU::DeleteActors(myRemovable);
1063       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
1064     }
1065   };
1066
1067   ProcessVoidEvent(new TRemoveFromStudy(this));
1068 }
1069
1070 SALOMEDS::SObject_var VISU::Curve_i::GetSObject()
1071 {
1072   return mySObj;
1073 }
1074
1075
1076 /*!
1077   Add container.
1078   id  - owner of the curve
1079 */
1080 void VISU::Curve_i::addContainer(const QString& id) {
1081   myContainers.insert(id);
1082 }
1083
1084 /*!
1085   Remove Container
1086   id  - entry of the container
1087 */
1088 void VISU::Curve_i::removeContainer(const QString& id) {
1089   myContainers.insert(id);
1090 }
1091
1092 /*!
1093   Get all owners of the curve.
1094   \return owners of the curve.
1095 */
1096 VISU::ContainerSet VISU::Curve_i::getContainers() const {
1097   return myContainers;
1098 }
1099
1100
1101 //----------------------------------------------------------------
1102 //                      Container Object
1103 //----------------------------------------------------------------
1104 int VISU::Container_i::myNbPresent = 0;
1105 const string VISU::Container_i::myComment  = "CONTAINER";
1106 /*!
1107   Generate unique name
1108 */
1109 QString VISU::Container_i::GenerateName()
1110 {
1111   return VISU::GenerateName( "Plot2DView", ++myNbPresent ).toLatin1().data();
1112 }
1113 /*!
1114   Gets comment string
1115 */
1116 const char* VISU::Container_i::GetComment() const
1117 {
1118   return myComment.c_str();
1119 }
1120 /*!
1121   Constructor
1122 */
1123 VISU::Container_i::Container_i( SALOMEDS::Study_ptr theStudy )
1124      : PrsObject_i( theStudy )
1125 {
1126 }
1127 /*!
1128   Destructor
1129 */
1130 VISU::Container_i::~Container_i()
1131 {
1132   MESSAGE("Container_i::~Container_i");
1133   myCurves.clear();
1134 }
1135 /*!
1136   Inserts curve into the container
1137 */
1138 void VISU::Container_i::AddCurve( Curve_ptr theCurve )
1139 {
1140   if ( GetStudyDocument()->_is_nil() )
1141     return;
1142   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1143   if ( mySO->_is_nil() )
1144     return;
1145   PortableServer::POA_ptr aPOA = GetPOA();
1146   Curve_i* pCurve = dynamic_cast<Curve_i*>( aPOA->reference_to_servant( theCurve ) );
1147   if( pCurve ) {
1148     QString entry( pCurve->GetEntry().c_str() );
1149     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( entry.toLatin1().data() );
1150     if ( !SO->_is_nil() && myCurves.indexOf( entry ) == -1 ) {
1151       myCurves.append( entry );
1152       SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1153       SALOMEDS::SObject_var newSO = Builder->NewObject( mySO );
1154       Builder->Addreference( newSO, SO );
1155       pCurve->addContainer(GetEntry().c_str());
1156     }
1157   }
1158 }
1159 /*!
1160   Removes curve from the container
1161 */
1162 void VISU::Container_i::RemoveCurve( Curve_ptr theCurve )
1163 {
1164   if ( GetStudyDocument()->_is_nil() )
1165     return;
1166   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1167   if ( mySO->_is_nil() )
1168     return;
1169   PortableServer::POA_ptr aPOA = GetPOA();
1170   Curve_i* pCurve = dynamic_cast<Curve_i*>( aPOA->reference_to_servant( theCurve ) );
1171   if( pCurve ) {
1172     QString entry( pCurve->GetEntry().c_str() );
1173     if ( myCurves.indexOf( entry ) != -1 ) {
1174       // found !!!
1175       myCurves.removeAll( entry );
1176       SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1177       SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1178       for ( ; CI->More(); CI->Next() ) {
1179         SALOMEDS::SObject_var childSO = CI->Value();
1180         SALOMEDS::SObject_var refSO;
1181         if ( childSO->ReferencedObject( refSO ) && !refSO->_is_nil() && entry == QString( refSO->GetID() ) ) {
1182           Builder->RemoveObject( childSO );
1183         }
1184       }
1185       pCurve->removeContainer(GetEntry().c_str());
1186     }
1187   }
1188 }
1189 /*!
1190   Gets number of curves in the container
1191 */
1192 CORBA::Long VISU::Container_i::GetNbCurves()
1193 {
1194   //  Update();
1195   return myCurves.count();
1196 }
1197 /*!
1198   Clears container
1199 */
1200 void VISU::Container_i::Clear()
1201 {
1202   if ( GetStudyDocument()->_is_nil() )
1203     return;
1204   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1205   if ( mySO->_is_nil() )
1206     return;
1207   QStringList toDelete;
1208   SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1209   for ( ; CI->More(); CI->Next() ) {
1210     toDelete.append( CI->Value()->GetID() );
1211   }
1212   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1213   for ( int i = 0; i < toDelete.count(); i++ ) {
1214     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( toDelete[i].toLatin1().data() );
1215     Builder->RemoveObject( SO );
1216   }
1217   myCurves.clear();
1218 }
1219 /*!
1220   Creates container object
1221 */
1222 VISU::Storable* VISU::Container_i::Create()
1223 {
1224   // generate name ...
1225   SetName(GenerateName().toLatin1().data(), false);
1226   // ... and build the object
1227   return Build( false );
1228 }
1229 /*!
1230   Builds presentation of container
1231 */
1232 VISU::Storable* VISU::Container_i::Build( int theRestoring )
1233 {
1234   if ( !theRestoring ) {
1235     // looking for component
1236     SALOMEDS::SComponent_var SComponent = VISU::FindOrCreateVisuComponent( GetStudyDocument() );
1237     // create SObject and set attributes
1238     QString aComment;
1239     aComment.sprintf("myComment=%s",GetComment());
1240     string anEntry = CreateAttributes( GetStudyDocument(),
1241                                        SComponent->GetID(),
1242                                        "",
1243                                        GetID(),
1244                                        GetName(),
1245                                        "",
1246                                        aComment.toLatin1().data(),
1247                                        true );
1248     mySObj = SALOMEDS::SObject::_duplicate(GetStudyDocument()->FindObjectID(anEntry.c_str()));
1249
1250     // Set icon
1251     SALOMEDS::StudyBuilder_var aStudyBuilder = GetStudyDocument()->NewBuilder();
1252     SALOMEDS::GenericAttribute_var anAttr;
1253     SALOMEDS::AttributePixMap_var  aPixmap;
1254     anAttr  = aStudyBuilder->FindOrCreateAttribute( mySObj, "AttributePixMap" );
1255     aPixmap = SALOMEDS::AttributePixMap::_narrow( anAttr );
1256     aPixmap ->SetPixMap("ICON_TREE_CONTAINER");
1257   }
1258   return this;
1259 }
1260 /*!
1261   Updates presentation of container
1262 */
1263 void VISU::Container_i::Update()
1264 {
1265   if ( GetStudyDocument()->_is_nil() )
1266     return;
1267   SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1268   SALOMEDS::SObject_var mySO = GetStudyDocument()->FindObjectID( GetEntry().c_str() );
1269   SALOMEDS::GenericAttribute_var anAttr;
1270   if ( !mySO->_is_nil() ) {
1271     QStringList toDelete;
1272     int i;
1273     for ( i = 0; i < myCurves.count(); i++ ) {
1274       SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID( myCurves[i].toLatin1().data() );
1275       if ( !SO->_is_nil() && Builder->FindAttribute( SO, anAttr, "AttributeIOR" ) ) {
1276         // if real Curve Object still exists
1277         SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1278         bool bFound = false;
1279         for ( ; CI->More(); CI->Next() ) {
1280           SALOMEDS::SObject_var childSO = CI->Value();
1281           SALOMEDS::SObject_var refSO;
1282           if ( childSO->ReferencedObject( refSO ) && !refSO->_is_nil() && myCurves[i] == QString( refSO->GetID() ) ) {
1283             bFound = true; break;
1284           }
1285         }
1286         if (! bFound ) {
1287           // create SObject referenced to real curve object if is not yet added
1288           SALOMEDS::SObject_var newSO = Builder->NewObject( mySO );
1289           Builder->Addreference( newSO, SO );
1290         }
1291       }
1292       else {
1293         // real Curve Object doesn't exist (might be removed)
1294         toDelete.append( myCurves[i] );
1295       }
1296     }
1297     for ( i = 0; i < toDelete.count(); i++ ) {
1298       myCurves.removeAll( toDelete[i] );
1299     }
1300     toDelete.clear();
1301     SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1302     for ( ; CI->More(); CI->Next() ) {
1303       SALOMEDS::SObject_var childSO = CI->Value();
1304       SALOMEDS::SObject_var refSO;
1305       if ( childSO->ReferencedObject( refSO ) && ( refSO->_is_nil() || !Builder->FindAttribute( refSO, anAttr, "AttributeIOR" ) ||
1306                                                    myCurves.indexOf( refSO->GetID() ) == -1 ) ) {
1307         toDelete.append( childSO->GetID() );
1308       }
1309     }
1310     for ( i = 0; i < toDelete.count(); i++ ) {
1311       SALOMEDS::ChildIterator_var CI = GetStudyDocument()->NewChildIterator( mySO );
1312       for ( ; CI->More(); CI->Next() ) {
1313         SALOMEDS::SObject_var childSO = CI->Value();
1314         if ( toDelete[i] == CI->Value()->GetID() ) {
1315           Builder->RemoveObject( childSO );
1316         }
1317       }
1318     }
1319   }
1320 }
1321 /*!
1322   Gets curve from container by index
1323   NB : curves are numbered from 1
1324 */
1325 VISU::Curve_i* VISU::Container_i::GetCurve( CORBA::Long theIndex )
1326 {
1327   if ( theIndex > 0 && theIndex <= myCurves.count()  ) {
1328     SALOMEDS::StudyBuilder_var Builder = GetStudyDocument()->NewBuilder();
1329     SALOMEDS::GenericAttribute_var anAttr;
1330     SALOMEDS::SObject_var SO = GetStudyDocument()->FindObjectID(myCurves[ theIndex-1 ].toLatin1().data() );
1331     CORBA::Object_var anObject = VISU::SObjectToObject( SO );
1332     if( !CORBA::is_nil( anObject ) ) {
1333       // if real Curve Object exists
1334       CORBA::Object_ptr aCurve = VISU::Curve::_narrow( anObject );
1335       if( !CORBA::is_nil( aCurve ) )
1336       return dynamic_cast<VISU::Curve_i*>(VISU::GetServant(aCurve).in());
1337     }
1338   }
1339   return NULL;
1340 }
1341 /*!
1342   Restores container data from the stream
1343 */
1344 VISU::Storable* VISU::Container_i::Restore( const Storable::TRestoringMap& theMap, SALOMEDS::SObject_ptr SO )
1345 {
1346   if(MYDEBUG) MESSAGE(GetComment());
1347   mySObj = SALOMEDS::SObject::_duplicate(SO);
1348   SetName(VISU::Storable::FindValue( theMap, "myName" ).toLatin1().data(), false);
1349   QString val = VISU::Storable::FindValue( theMap, "myCurves" );
1350   myCurves = val.split( "*", QString::SkipEmptyParts );
1351   return Build( true );
1352 }
1353 /*!
1354   Flushes container data into the stream
1355 */
1356 void VISU::Container_i::ToStream( std::ostringstream& theStr )
1357 {
1358   Storable::DataToStream( theStr, "myName",   GetName().c_str() );
1359   Storable::DataToStream( theStr, "myCurves", myCurves.join( QString( "*" ) ) );
1360 //  theStr<<" myName "<<myName;
1361 //  theStr<<" myCurves "<<myCurves.join( QString( "*" ) ).latin1()<<"* ";
1362 }
1363 /*!
1364   Called from engine to restore container from the file
1365 */
1366 VISU::Storable* VISU::Container_i::StorableEngine(SALOMEDS::SObject_ptr theSObject,
1367                                                   const Storable::TRestoringMap& theMap,
1368                                                   const std::string& thePrefix,
1369                                                   CORBA::Boolean theIsMultiFile)
1370 {
1371   SALOMEDS::Study_var aStudy = theSObject->GetStudy();
1372   VISU::Container_i* pResent = new VISU::Container_i( aStudy );
1373   return pResent->Restore( theMap, theSObject );
1374 }
1375
1376 void VISU::Container_i::RemoveFromStudy()
1377 {
1378   struct TRemoveFromStudy: public SALOME_Event
1379   {
1380     VISU::Container_i* myRemovable;
1381     TRemoveFromStudy(VISU::Container_i* theRemovable):
1382       myRemovable(theRemovable)
1383     {}
1384     
1385     virtual
1386     void
1387     Execute()
1388     {
1389       VISU::RemoveFromStudy(myRemovable->GetSObject(),false);
1390     }
1391   };
1392
1393   ProcessVoidEvent(new TRemoveFromStudy(this));
1394 }
1395
1396 SALOMEDS::SObject_var VISU::Container_i::GetSObject()
1397 {
1398   return mySObj;
1399 }
1400
1401 SALOMEDS::SObject_var
1402 VISU::ImportTables(const char* theFileName, SALOMEDS::Study_ptr theStudy,
1403                    bool theFirstStrAsTitle)
1404 {
1405   // Set "C" numeric locale to import numbers correctly
1406   Kernel_Utils::Localizer loc;
1407
1408   TTableContainer aContainer;
1409   ImportTables( theFileName, aContainer, theFirstStrAsTitle );
1410   if ( aContainer.empty() ) 
1411     return SALOMEDS::SObject::_nil();
1412
1413   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
1414   SALOMEDS::SComponent_var theSComponent = VISU::FindOrCreateVisuComponent(theStudy);
1415   SALOMEDS::SObject_var aFileObject = aStudyBuilder->NewObject(theSComponent);
1416   SALOMEDS::GenericAttribute_var anAttr =
1417     aStudyBuilder->FindOrCreateAttribute(aFileObject, "AttributeName");
1418   SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
1419   QFileInfo aFileInfo(theFileName);
1420   aName->SetValue( aFileInfo.fileName().toLatin1().data());
1421   anAttr = aStudyBuilder->FindOrCreateAttribute(aFileObject, "AttributeString");
1422   SALOMEDS::AttributeString_var aComment = SALOMEDS::AttributeString::_narrow(anAttr);
1423   QString aString;
1424   aString.sprintf("myComment=ImportTables;myFileName=%s;myFirstStrAsTitle=%d",
1425                   aFileInfo.absoluteFilePath().toLatin1().data(),theFirstStrAsTitle);
1426   aComment->SetValue(aString.toLatin1().data());
1427   for(int i = 0, iEnd = aContainer.size(); i < iEnd; i++) {
1428     PTableIDMapper aTableIDMapper = aContainer[i];
1429     const TTable2D& aTable2D = *aTableIDMapper;
1430     SALOMEDS::SObject_var aRealObject = aStudyBuilder->NewObject(aFileObject);
1431     anAttr = aStudyBuilder->FindOrCreateAttribute(aRealObject, "AttributeName");
1432     aName = SALOMEDS::AttributeName::_narrow(anAttr);
1433     if(MYDEBUG) MESSAGE("aTable2D.myTitle = "<<aTable2D.myTitle);
1434     if ( aTable2D.myTitle != "" ) {
1435       aName->SetValue(aTable2D.myTitle.c_str());
1436     }
1437     else {
1438       QString aNewName;
1439       aNewName.sprintf("Table:%d",i);
1440       aName->SetValue(aNewName.toLatin1().data());
1441     }
1442
1443     anAttr = aStudyBuilder->FindOrCreateAttribute(aRealObject, "AttributeTableOfReal");
1444     SALOMEDS::AttributeTableOfReal_var aTableOfReal = SALOMEDS::AttributeTableOfReal::_narrow(anAttr);
1445     aTableOfReal->SetTitle(aTable2D.myTitle.c_str());
1446     TTable2D aNewTable2D;
1447     aTable2D.getColumns(aNewTable2D);
1448     int kEnd = aNewTable2D.myRows[0].myValues.size();
1449     // check empty columns
1450     TColStd_MapOfInteger EmptyColumns;
1451     for(int j = 0, jEnd = aNewTable2D.myRows.size(); j < jEnd; j++) {
1452       bool hasVal = false;
1453       for(int k = 0; k < kEnd; k++) {
1454         QString aVal = aNewTable2D.myRows[j].myValues[k].c_str();
1455         bool anIsOk = false;
1456         double aValue = aVal.toDouble(&anIsOk);
1457         if(anIsOk) {
1458           hasVal = true;
1459           break;
1460         }
1461       }
1462       if(!hasVal) {
1463         EmptyColumns.Add(j);
1464       }
1465     }
1466     // create table of real
1467     aTableOfReal->SetNbColumns( kEnd - EmptyColumns.Extent() );
1468     int currNum = -1;
1469     for(int j = 0, jEnd = aNewTable2D.myRows.size(); j < jEnd; j++) {
1470       if( EmptyColumns.Contains(j) ) continue;
1471       currNum++;
1472       if(MYDEBUG) MESSAGE("j = "<<j<<"; kEnd = "<<kEnd);
1473       for(int k = 0; k < kEnd; k++) {
1474         QString aVal = aNewTable2D.myRows[j].myValues[k].c_str();
1475         bool anIsOk = false;
1476         double aValue = aVal.toDouble(&anIsOk);
1477         if( anIsOk && !aVal.contains("NAN",Qt::CaseInsensitive) &&
1478             !aVal.contains("INF",Qt::CaseInsensitive) ) {
1479           aTableOfReal->PutValue(aValue,currNum+1,k+1);
1480         }
1481       }
1482       aTableOfReal->SetRowTitle(currNum+1,aNewTable2D.myRows[j].myTitle.c_str());
1483       aTableOfReal->SetRowUnit(currNum+1,aNewTable2D.myRows[j].myUnit.c_str());
1484     }
1485     for(int k = 0; k < kEnd; k++)
1486       aTableOfReal->SetColumnTitle(k+1,aNewTable2D.myColumnTitles[k].c_str());
1487   }
1488   return aFileObject;
1489 }
1490
1491
1492 //=======================================================================
1493 //function : updateStrForCSV
1494 //purpose  : auxilary for ExportTableToFile
1495 //=======================================================================
1496 void updateStrForCSV(QString& aStr, const char aSep)
1497 {
1498   int index = aStr.indexOf('"');
1499   while(index>=0) {
1500     aStr.insert(index,'"');
1501     if( index+2 >= aStr.size() ) break;
1502     index = aStr.indexOf('"',index+2);
1503   }
1504   index = aStr.indexOf(aSep);
1505   if(index>=0) {
1506     // current string contains separator => need to use "..."
1507     aStr.insert(0,'"');
1508     aStr.push_back('"');
1509   }
1510 }
1511
1512
1513 //=======================================================================
1514 //function : ExportTableToFile
1515 //purpose  : 
1516 //=======================================================================
1517 template<class TTableAttr> bool ExportTableToFile(const TTableAttr& aTabAttr,
1518                                                   const char* theFileName)
1519 {
1520   if (CORBA::is_nil(aTabAttr))
1521     return false;
1522
1523   // Set "C" numeric locale to save numbers correctly
1524   Kernel_Utils::Localizer loc;
1525
1526   QFile aFile(theFileName);
1527   aFile.open(QIODevice::WriteOnly);
1528
1529   /* extract the table info and write it into file */
1530
1531   QString aTitle(aTabAttr->GetTitle()); /*Table title*/
1532   int aRowsNb = aTabAttr->GetNbRows();
1533   int aColNb  = aTabAttr->GetNbColumns();
1534
1535   SALOMEDS::StringSeq_var aRowTitles = aTabAttr->GetRowTitles();
1536   SALOMEDS::StringSeq_var aRowUnits = aTabAttr->GetRowUnits();
1537   SALOMEDS::StringSeq_var aColumnTitles = aTabAttr->GetColumnTitles();
1538
1539   //--------------------------------------------------
1540   //    write as *.csv file if it is needed
1541   //--------------------------------------------------
1542   QString tmp(theFileName);
1543   tmp = tmp.trimmed();
1544   tmp = tmp.right(3).trimmed();
1545   if( tmp == QString("csv") ) {
1546     const char aSep = ',';
1547     // write column titles
1548     QString aLine(aRowTitles[0]);
1549     updateStrForCSV(aLine,aSep);
1550     for(int i=1; i<aRowsNb; i++) {
1551       aLine += aSep;
1552       QString aTmp(aRowTitles[i]);
1553       updateStrForCSV(aTmp,aSep);
1554       aLine += aTmp;
1555     }
1556     aLine += "\n";
1557     aFile.write(aLine.toLatin1() );
1558     // write table data
1559     QString aValue;
1560     for (int j = 1; j <= aColNb; j++) {
1561       QString aLine = "";
1562       if(aTabAttr->HasValue(j,1)) {
1563         aLine = aValue.sprintf("%.16g",(double)aTabAttr->GetValue(1,j));
1564       }
1565       for (int i = 2; i <= aRowsNb; i++) {
1566         if(aTabAttr->HasValue(i,j)) {
1567           aLine += aSep + aValue.sprintf("%.16g",(double)aTabAttr->GetValue(i,j));
1568         }
1569         else aLine += aSep;
1570       }
1571       aLine += "\n";
1572       aFile.write(aLine.toLatin1() );
1573     }
1574
1575     aFile.close();
1576     return true;
1577   }
1578   //--------------------------------------------------
1579   //       end of writing as *.csv file
1580   //--------------------------------------------------
1581
1582   /* The given table is rare (some cells is empty) or not? */
1583   bool isRareTable = false;
1584   for (int i = 1; i <= aRowsNb; i++)
1585     for (int j = 1; j <= aColNb && !isRareTable; j++)
1586       isRareTable = !aTabAttr->HasValue(i,j);
1587
1588   QString aLine;
1589   if (isRareTable) {
1590     /* Separate the given table to 2D tables and write these ones to the file */
1591     QString anAbscissTitle(aRowTitles[0]); /*Absciss row title (X coord)*/
1592     anAbscissTitle.trimmed();
1593     QString anAbscissUnit(aRowUnits[0]);
1594     anAbscissUnit.trimmed();
1595     if (aRowsNb > 2 && aTitle.length() )  aTitle = aTitle + " - ";
1596
1597     for (int i = 2; i <= aRowsNb; i++ )
1598       {
1599         /* TITLE */
1600         QString anOrdinate(aRowTitles[i-1]), aTail;
1601         anOrdinate.trimmed();
1602
1603         aLine = "#TITLE: " + aTitle +
1604           ((anOrdinate.length())?  anOrdinate :
1605                                   (aRowsNb>2)? aTail.sprintf("%d",i-1) : aTail.sprintf("") ) + "\n";
1606         aFile.write(aLine.toLatin1() );
1607
1608         /* COLUMN_TITLES */
1609         if ( anAbscissTitle.length() || anOrdinate.length() ) {
1610           aLine = "#COLUMN_TITLES: " + anAbscissTitle + " | " + anOrdinate;
1611           int tmpind = aLine.indexOf("\n");
1612           while(tmpind>=0) {
1613             aLine.remove(tmpind,1);
1614             tmpind = aLine.indexOf("\n");
1615           }
1616           aLine += "\n";
1617           aFile.write(aLine.toLatin1() );
1618         }
1619
1620         /* COLUMN_UNITS */
1621         aLine = anAbscissUnit + " " +aRowUnits[i-1];
1622         if (!aLine.trimmed().isEmpty()) {
1623           aLine = "#COLUMN_UNITS: " + aLine  + "\n";
1624           aFile.write(aLine.toLatin1() );
1625         }
1626
1627         /* CURVE COORDINATES */
1628         for (int j = 1; j <= aColNb; j++)
1629           {
1630             if ( aTabAttr -> HasValue(i,j) &&  aTabAttr -> HasValue(1, j)) {
1631               aLine = aLine.sprintf("%.16g %.16g",
1632                                     (double)(aTabAttr->GetValue(1,j)),
1633                                     (double)(aTabAttr->GetValue(i,j)));  /* aTabAttr->GetValue(1,j) - X coord */
1634               if ( !aLine.trimmed().isEmpty() ) {
1635                 QString aColTitle(aColumnTitles[j-1]);
1636                 if ( !aColTitle.trimmed().isEmpty() )
1637                   aLine = aLine + "  #TITLE: " + aColTitle ;
1638                 aFile.write(QString(aLine + "\n").toLatin1() );
1639               }
1640             }
1641           }
1642         aFile.write("\n", 1);
1643       }
1644   }//end of if (isRareTable)
1645   else {
1646     /* Write the table in the file without separating */
1647     /* TITLE */
1648     aLine = "#TITLE: " + aTitle + "\n";
1649     aFile.write(aLine.toLatin1());
1650
1651     /* COLUMN_TITLES  and COLUMN_UNITS */
1652     QString aTitlesSep = "";
1653     QString aUnitsSep  = "";
1654     QString aTitlesStr = "#COLUMN_TITLES: ";
1655     QString aUnitsStr  = "#COLUMN_UNITS: ";
1656     for (int i = 1; i <= aRowsNb; i++) {
1657       if (!QString(aRowTitles[i-1]).trimmed().isEmpty()) {
1658         aTitlesStr += (aTitlesSep + aRowTitles[i-1]);
1659         if (aTitlesSep.isEmpty()) aTitlesSep = " | ";
1660       }
1661       if (!QString(aRowUnits[i-1]).trimmed().isEmpty()) {
1662         aUnitsStr += (aUnitsSep + aRowUnits[i-1]);
1663         if (aUnitsSep.isEmpty()) aUnitsSep = " ";
1664       }
1665     }
1666     int tmpind = aTitlesStr.indexOf("\n");
1667     while(tmpind>=0) {
1668       aTitlesStr.remove(tmpind,1);
1669       tmpind = aTitlesStr.indexOf("\n");
1670     }
1671     aTitlesStr += "\n";
1672     aUnitsStr  += "\n";
1673     aFile.write(aTitlesStr.toLatin1());
1674     aFile.write(aUnitsStr.toLatin1());
1675
1676     /* CURVE COORDINATES */
1677     QString aSep, aValue, aColTitle;
1678     for (int j = 1; j <= aColNb; j++) {
1679       aLine = ""; aSep  = "";
1680       for (int i = 1; i <= aRowsNb; i++) {
1681         aLine += (aSep + aValue.sprintf("%.16g", (double)(aTabAttr->GetValue(i,j))));
1682         if (aSep.isEmpty()) aSep = " ";
1683       }
1684       if (!aLine.trimmed().isEmpty()) {
1685         aColTitle = aColumnTitles[j-1];
1686         if (!aColTitle.trimmed().isEmpty())
1687           aLine = aLine + "  #TITLE: " + aColTitle;
1688         aLine += "\n";
1689         aFile.write(aLine.toLatin1());
1690       }
1691     }
1692   } //end of else
1693
1694   aFile.close();
1695   return true;
1696 }
1697
1698 bool VISU::ExportTableToFile(SALOMEDS::SObject_ptr theTable, const char* theFileName)
1699 {
1700   //Find table
1701   SALOMEDS::GenericAttribute_var anAttr ;
1702   if (theTable->FindAttribute(anAttr, "AttributeTableOfReal")) {
1703     SALOMEDS::AttributeTableOfReal_var aTabAttr =
1704       SALOMEDS::AttributeTableOfReal ::_narrow(anAttr);
1705     return ExportTableToFile ( aTabAttr , theFileName);
1706   }
1707   else if (theTable->FindAttribute(anAttr, "AttributeTableOfInteger")) {
1708     SALOMEDS::AttributeTableOfInteger_var aTabAttr =
1709       SALOMEDS::AttributeTableOfInteger ::_narrow(anAttr);
1710     return ExportTableToFile ( aTabAttr , theFileName);
1711   }
1712   return false;
1713 }