Salome HOME
adbf8f9a47bee0708b612a559ee7216c421c31ea
[modules/visu.git] / src / VISU_I / VISU_ResultUtils.cc
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //  VISU OBJECT : interactive object for VISU entities implementation
21 //  File   : VISU_ResultUtils.cc
22 //  Author : Alexey PETROV
23 //  Module : VISU
24 //
25 #include "VISU_ResultUtils.hh"
26
27 #include "SUIT_Session.h"
28 #include "SALOME_Event.h"
29 #include "SalomeApp_Study.h"
30 #include "SalomeApp_Application.h"
31
32 #include "VISU_Convertor.hxx"
33 #include "VISU_ConvertorUtils.hxx"
34
35 #include <QFileInfo>
36 #include <QFile>
37 #include <QDir>
38
39 #include <boost/thread/recursive_mutex.hpp>
40 #include <boost/thread/thread.hpp>
41 #include <boost/bind.hpp>
42
43 #ifdef _DEBUG_
44 static int MYTIMEDEBUG = 0;
45 #else
46 static int MYTIMEDEBUG = 0;
47 #endif
48
49 using namespace std;
50
51 namespace VISU
52 {
53   //----------------------------------------------------------------------------
54   typedef boost::recursive_mutex TMutex;
55   typedef TMutex::scoped_lock TLock;
56
57   static TMutex myMutex;
58
59   //----------------------------------------------------------------------------
60   TResultManager
61   ::TResultManager(Result_i* theResult):
62     myResult(theResult)
63   {
64     myResult->Register();
65   }
66
67
68   //----------------------------------------------------------------------------
69   TResultManager
70   ::~TResultManager()
71   {
72     myResult->UnRegister();
73   }
74
75
76   //----------------------------------------------------------------------------
77   TTransactionManager
78   ::TTransactionManager(_PTR(Study) theStudyDocument):
79     myStudyBuilder(theStudyDocument->NewBuilder())
80   {
81     TLock aLock(myMutex);
82     myStudyBuilder->NewCommand();
83   }
84
85
86   //----------------------------------------------------------------------------
87   TTransactionManager
88   ::~TTransactionManager()
89   {
90     TLock aLock(myMutex);
91     myStudyBuilder->CommitCommand();
92   }
93
94
95   //----------------------------------------------------------------------------
96   TUpdateObjBrowser
97   ::TUpdateObjBrowser(const int theStudyId, CORBA::Boolean* theIsDone):
98     myStudyId(theStudyId),
99     myIsDone(theIsDone)
100   {}
101     
102   
103   //----------------------------------------------------------------------------
104   void
105   TUpdateObjBrowser
106   ::Execute()
107   {
108     TLock aLock(myMutex);
109     SUIT_Session* aSession = SUIT_Session::session();
110     QList<SUIT_Application*> anApplications = aSession->applications();
111     QListIterator<SUIT_Application*> anIter (anApplications);
112     while (anIter.hasNext()) {
113       SUIT_Application* aSApp = anIter.next();
114       if(SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>(aSApp)){
115         if (SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(anApp->activeStudy())) {
116           if (_PTR(Study) aCStudy = aStudy->studyDS()) {
117             if (myStudyId == aCStudy->StudyId()) {
118               TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::updateObjectBrowser");
119               anApp->updateObjectBrowser();
120               *myIsDone = true;
121               break;
122             }
123           }
124         }
125       }
126     }
127   }
128
129
130   //----------------------------------------------------------------------------
131   QString
132   GenerateName(const std::string& theName)
133   {
134     TLock aLock(myMutex);
135
136     typedef std::map<std::string, int> TNameMap;
137     static TNameMap aMap;
138
139     TNameMap::const_iterator anIter = aMap.find(theName);
140     QString aResult;
141     if (anIter == aMap.end()) {
142       aMap[theName] = 0;
143       aResult = theName.c_str();
144     } else {
145       aResult = GenerateName(theName,++aMap[theName]);
146     }
147     return aResult;
148   }
149   
150
151   //----------------------------------------------------------------------------
152   bool
153   SplitName(const std::string& theName,
154             std::string& theBase,
155             std::string& theSuffix,
156             char theDelimeter)
157   {
158     size_t aPosition = theName.rfind(theDelimeter);
159     if(aPosition == std::string::npos){
160       theBase = theName;
161       theSuffix = "";
162       return false;
163     }
164
165     theBase = theName.substr(0, aPosition);
166     theSuffix = theName.substr(aPosition);
167     return true;
168   }
169   
170
171   //----------------------------------------------------------------------------
172   std::string
173   MakeFileName(const std::string& theName,
174                const void* thePointer)
175   {
176     std::ostringstream aStream;    
177     aStream<<theName<<"_"<<thePointer;
178     return aStream.str();
179   }
180   
181
182   //----------------------------------------------------------------------------
183   QString 
184   GenerateFieldName(const std::string& theName, 
185                     const std::string& theUnits)
186   {
187     QString aName;
188     const string tmp (theUnits.size(),' ');
189     if (theUnits == "" || theUnits == tmp)
190       aName = QString("%1, -").arg(theName.c_str());
191     else
192       aName = QString("%1, %2").arg(theName.c_str()).arg(theUnits.c_str());
193     aName = aName.simplified();
194     return aName;
195   }
196
197
198   //----------------------------------------------------------------------------
199   void
200   CreateReference(_PTR(Study) theStudyDocument,
201                   const std::string& theFatherEntry, 
202                   const std::string& theRefEntry)
203   {
204     _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
205     _PTR(SObject) aFather = theStudyDocument->FindObjectID(theFatherEntry);
206     _PTR(SObject) aNewObj = aStudyBuilder->NewObject(aFather);
207     _PTR(SObject) aRefSObj = theStudyDocument->FindObjectID(theRefEntry);
208     aStudyBuilder->Addreference(aNewObj,aRefSObj);
209   }
210
211
212   //----------------------------------------------------------------------------
213   void 
214   RemoveSObject(_PTR(Study) theStudyDocument,
215                 const string& theEntry)
216   {
217     _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
218     _PTR(SObject) aSObject = theStudyDocument->FindObjectID(theEntry);
219     aStudyBuilder->RemoveObject(aSObject);
220   }
221
222
223   //----------------------------------------------------------------------------
224   void
225   BuildEntities(Result_i* theResult,
226                 Result_i::PInput theInput,
227                 CORBA::Boolean* theIsDone,
228                 const std::string& theResultEntry,
229                 CORBA::Boolean theIsAtOnce,
230                 CORBA::Boolean theIsBuildGroups,
231                 CORBA::Boolean theIsBuildFields,
232                 CORBA::Boolean theIsBuildParts,
233                 _PTR(Study) theStudy)
234   {
235     if(*theIsDone)
236       return;
237
238     TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::BuildEntities");
239     TResultManager aResultManager(theResult);
240     TTransactionManager aTransactionManager(theStudy);
241
242     {
243       TTimerLog aTimerLog(MYTIMEDEBUG,"theInput->BuildEntities");
244       theInput->BuildEntities();
245     }
246
247     QString aComment,aTmp;
248     const TMeshMap& aMeshMap = theInput->GetMeshMap();
249     TMeshMap::const_iterator aMeshMapIter = aMeshMap.begin();
250     for(; aMeshMapIter != aMeshMap.end(); aMeshMapIter++){
251       const string& aMeshName = aMeshMapIter->first;
252       const PMesh& aMesh = aMeshMapIter->second;
253       const TMeshOnEntityMap& aMeshOnEntityMap = aMesh->myMeshOnEntityMap;
254       if(aMeshOnEntityMap.empty()) 
255         continue;
256       aComment = QString("myComment=MESH;myName=%1;myDim=%2");
257       aComment = aComment.arg(aMeshName.c_str());
258       aComment = aComment.arg(aMesh->myDim);
259       aMesh->myEntry = 
260         CreateAttributes(theStudy,
261                          theResultEntry,
262                          NO_ICON,
263                          NO_IOR,
264                          aMeshName,
265                          NO_PERFSITENT_REF,
266                          aComment.toLatin1().data(),
267                          true);
268     
269       aComment = QString("myComment=FAMILIES;myMeshName=%1").arg(aMeshName.c_str());
270       std::string aSubMeshesEntry = 
271         CreateAttributes(theStudy,
272                          aMesh->myEntry,
273                          NO_ICON,
274                          NO_IOR,
275                          "Families",
276                          NO_PERFSITENT_REF,
277                          aComment.toLatin1().data(),
278                          true);
279
280       if(theIsBuildGroups){
281         aMesh->myGroupsEntry =
282           CreateAttributes(theStudy,
283                            aMesh->myEntry,
284                            NO_ICON,
285                            NO_IOR,
286                            NO_NAME,
287                            NO_PERFSITENT_REF,
288                            NO_COMMENT,
289                            true);
290       }
291         
292       if(theIsBuildFields){
293         aMesh->myFieldsEntry =
294           CreateAttributes(theStudy,
295                            aMesh->myEntry,
296                            NO_ICON,
297                            NO_IOR,
298                            NO_NAME,
299                            NO_PERFSITENT_REF,
300                            NO_COMMENT,
301                            true);
302       }
303
304       if(theIsBuildParts){
305         aMesh->myPartsEntry =
306           CreateAttributes(theStudy,
307                            aMesh->myEntry,
308                            NO_ICON,
309                            NO_IOR,
310                            NO_NAME,
311                            NO_PERFSITENT_REF,
312                            NO_COMMENT,
313                            true);
314       }
315
316       //Import entities
317       TMeshOnEntityMap::const_iterator aMeshOnEntityMapIter = aMeshOnEntityMap.begin();
318       for(; aMeshOnEntityMapIter != aMeshOnEntityMap.end(); aMeshOnEntityMapIter++){
319         const TEntity& anEntity = aMeshOnEntityMapIter->first;
320         const PMeshOnEntity& aMeshOnEntity = aMeshOnEntityMapIter->second;
321         
322         string anEntityName;
323         switch(anEntity){
324         case NODE_ENTITY: 
325           anEntityName = "onNodes"; 
326           break;
327         case EDGE_ENTITY: 
328           anEntityName = "onEdges"; 
329           break;
330         case FACE_ENTITY: 
331           anEntityName = "onFaces"; 
332           break;
333         case CELL_ENTITY: 
334           anEntityName = "onCells"; 
335           break;
336         default:
337         continue;
338         }
339         
340         aComment = QString("myComment=ENTITY;myMeshName=%1;myId=%2");
341         aComment = aComment.arg(aMeshName.c_str());
342         aComment = aComment.arg(anEntity);
343         
344         aMeshOnEntity->myEntry = 
345           CreateAttributes(theStudy, 
346                            aSubMeshesEntry, 
347                            NO_ICON,
348                            NO_IOR,
349                            anEntityName.c_str(),
350                            NO_PERFSITENT_REF,
351                            aComment.toLatin1().data(), 
352                            true);
353       }
354     }
355     
356     ProcessVoidEvent(new TUpdateObjBrowser(theStudy->StudyId(),theIsDone));
357   }
358
359
360   //----------------------------------------------------------------------------
361   void
362   BuildGroups(Result_i* theResult,
363               Result_i::PInput theInput,
364               CORBA::Boolean* theIsDone,
365               CORBA::Boolean theIsBuild,
366               CORBA::Boolean theIsAtOnce,
367               _PTR(Study) theStudy)
368   {
369     if(!theIsBuild || *theIsDone)
370       return;
371
372     TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::BuildGroups");
373     TResultManager aResultManager(theResult);
374     TTransactionManager aTransactionManager(theStudy);
375     
376     {
377       TTimerLog aTimerLog(MYTIMEDEBUG,"theInput->BuildGroups");
378       theInput->BuildGroups();
379     }
380
381     QString aComment,aTmp;
382     const TMeshMap& aMeshMap = theInput->GetMeshMap();
383     TMeshMap::const_iterator aMeshMapIter = aMeshMap.begin();
384     for(; aMeshMapIter != aMeshMap.end(); aMeshMapIter++){
385       const string& aMeshName = aMeshMapIter->first;
386       const PMesh& aMesh = aMeshMapIter->second;
387       
388       const TMeshOnEntityMap& aMeshOnEntityMap = aMesh->myMeshOnEntityMap;
389       if(aMeshOnEntityMap.empty()) 
390         continue;
391       
392       TMeshOnEntityMap::const_iterator aMeshOnEntityMapIter = aMeshOnEntityMap.begin();
393       for(; aMeshOnEntityMapIter != aMeshOnEntityMap.end(); aMeshOnEntityMapIter++){
394         const TEntity& anEntity = aMeshOnEntityMapIter->first;
395         const PMeshOnEntity& aMeshOnEntity = aMeshOnEntityMapIter->second;
396         const TFamilyMap& aFamilyMap = aMeshOnEntity->myFamilyMap;
397         TFamilyMap::const_iterator aFamilyMapIter = aFamilyMap.begin();
398         for(; aFamilyMapIter != aFamilyMap.end(); aFamilyMapIter++){
399           const string& aFamilyName = aFamilyMapIter->first;
400           const PFamily& aFamily = aFamilyMapIter->second;
401           aComment=QString("myComment=FAMILY;myMeshName=%1;myEntityId=%2;myName=%3");
402           aComment=aComment.arg(aMeshName.c_str());
403           aComment=aComment.arg(anEntity);
404           aComment=aComment.arg(aFamilyName.c_str());
405           aFamily->myEntry = CreateAttributes(theStudy,
406                                               aMeshOnEntity->myEntry,
407                                               NO_ICON,
408                                               NO_IOR,
409                                               aFamilyName,
410                                               NO_PERFSITENT_REF,
411                                               aComment.toLatin1().data(),
412                                               true);
413         }
414       }
415       //Importing groups
416       const TGroupMap& aGroupMap = aMesh->myGroupMap;
417       if(!aGroupMap.empty()){
418         aComment = QString("myComment=GROUPS;myMeshName=%1").arg(aMeshName.c_str());
419         
420         CreateAttributes(theStudy,
421                          aMesh->myGroupsEntry,
422                          NO_ICON,
423                          NO_IOR,
424                          "Groups",
425                          NO_PERFSITENT_REF,
426                          aComment.toLatin1().data(),
427                          false);
428                          
429         TGroupMap::const_iterator aGroupMapIter = aGroupMap.begin();
430         for(; aGroupMapIter != aGroupMap.end(); aGroupMapIter++){
431           const string& aGroupName = aGroupMapIter->first;
432           const PGroup& aGroup = aGroupMapIter->second;
433           aComment = QString("myComment=GROUP;myMeshName=%1;myName=%2").arg(aMeshName.c_str()).arg(aGroupName.c_str());
434           aGroup->myEntry = CreateAttributes(theStudy,
435                                              aMesh->myGroupsEntry,
436                                              NO_ICON,
437                                              NO_IOR,
438                                              aGroupName,
439                                              NO_PERFSITENT_REF,
440                                              aComment.toLatin1().data(),
441                                              true);
442           const TFamilySet& aFamilySet = aGroup->myFamilySet;
443           TFamilySet::const_iterator aFamilyIter = aFamilySet.begin();
444           for(; aFamilyIter != aFamilySet.end(); aFamilyIter++){
445             const PFamily& aFamily = (*aFamilyIter).second;
446             CreateReference(theStudy,
447                             aGroup->myEntry,
448                             aFamily->myEntry);
449           }
450         }
451       }else if(!theIsAtOnce)
452         RemoveSObject(theStudy,
453                       aMesh->myGroupsEntry);
454     }
455     
456     ProcessVoidEvent(new TUpdateObjBrowser(theStudy->StudyId(),theIsDone));
457   }
458
459
460   //----------------------------------------------------------------------------
461   void
462   BuildFields(Result_i* theResult,
463               Result_i::PInput theInput,
464               CORBA::Boolean* theIsDone,
465               CORBA::Boolean theIsBuild,
466               CORBA::Boolean theIsAtOnce,
467               _PTR(Study) theStudy)
468   {
469     if(!theIsBuild || *theIsDone)
470       return;
471
472     TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::BuildFields");
473     TResultManager aResultManager(theResult);
474     TTransactionManager aTransactionManager(theStudy);
475
476     {
477       TTimerLog aTimerLog(MYTIMEDEBUG,"theInput->BuildFields");
478       theInput->BuildFields();
479     }
480
481     QString aComment,aTmp;
482     const TMeshMap& aMeshMap = theInput->GetMeshMap();
483     TMeshMap::const_iterator aMeshMapIter = aMeshMap.begin();
484
485     for(; aMeshMapIter != aMeshMap.end(); aMeshMapIter++)
486     {
487       const string& aMeshName = aMeshMapIter->first;
488       const PMesh& aMesh = aMeshMapIter->second;
489
490       const TMeshOnEntityMap& aMeshOnEntityMap = aMesh->myMeshOnEntityMap;
491       if(aMeshOnEntityMap.empty()) 
492         continue;
493
494       //Import fields
495       bool anIsFieldsEntryUpdated = false;
496       TMeshOnEntityMap::const_iterator aMeshOnEntityMapIter = aMeshOnEntityMap.begin();
497
498       for(; aMeshOnEntityMapIter != aMeshOnEntityMap.end(); aMeshOnEntityMapIter++)
499       {
500         const TEntity& anEntity = aMeshOnEntityMapIter->first;
501         const PMeshOnEntity& aMeshOnEntity = aMeshOnEntityMapIter->second;
502         const TFieldMap& aFieldMap = aMeshOnEntity->myFieldMap;
503         TFieldMap::const_iterator aFieldMapIter = aFieldMap.begin();
504         
505         for(; aFieldMapIter != aFieldMap.end(); aFieldMapIter++)
506         {
507           if(!anIsFieldsEntryUpdated)
508           {
509             aComment = "";
510             aComment.append("myComment=FIELDS;");
511             aComment.append("myMeshName=");aComment.append(aMeshName.c_str());
512             
513             CreateAttributes(theStudy,
514                              aMesh->myFieldsEntry,
515                              NO_ICON,
516                              NO_IOR,
517                              "Fields",
518                              NO_PERFSITENT_REF,
519                              aComment.toLatin1().data(),
520                              false);
521             anIsFieldsEntryUpdated = true;
522           }
523         
524           const string& aFieldName = aFieldMapIter->first;
525           const PField& aField = aFieldMapIter->second;
526           const TValField& aValField = aField->myValField;
527           QString aFieldNameWithUnit = GenerateFieldName(aFieldName,aField->myUnitNames[0]);
528           aComment = QString("myComment=FIELD;myMeshName=%1;myEntityId=%2;myName=%3;myNbTimeStamps=%4;myNumComponent=%5");
529           aComment = aComment.arg(aMeshName.c_str());
530           aComment = aComment.arg(anEntity);
531           aComment = aComment.arg(aFieldName.c_str());
532           aComment = aComment.arg(aValField.size());
533           aComment = aComment.arg(aField->myNbComp);
534           
535           aField->myEntry = CreateAttributes(theStudy,
536                                             aMesh->myFieldsEntry,
537                                             NO_ICON,
538                                             NO_IOR,
539                                             aFieldNameWithUnit.toLatin1().data(),
540                                             NO_PERFSITENT_REF,
541                                             aComment.toLatin1().data(),
542                                             true);
543
544           CreateReference(theStudy,
545                           aField->myEntry,
546                           aMeshOnEntity->myEntry);
547
548           TValField::const_iterator aValFieldIter = aValField.begin();
549           
550           for(; aValFieldIter != aValField.end(); aValFieldIter++)
551           {
552             int aTimeStamp = aValFieldIter->first;
553             const PValForTime& aValForTime = aValFieldIter->second;
554             aComment = QString("myComment=TIMESTAMP;myMeshName=%1;myEntityId=%2;myFieldName=%3;myTimeStampId=%4;myNumComponent=%5");
555             aComment = aComment.arg(aMeshName.c_str());
556             aComment = aComment.arg(anEntity);
557             aComment = aComment.arg(aFieldName.c_str());
558             aComment = aComment.arg(aTimeStamp);
559             aComment = aComment.arg(aField->myNbComp);
560             
561             string aTimeStampId = VISU_Convertor::GenerateName(aValForTime->myTime);
562             
563             aValForTime->myEntry = CreateAttributes(theStudy,
564                                                     aField->myEntry,
565                                                     NO_ICON,
566                                                     NO_IOR,
567                                                     aTimeStampId,
568                                                     NO_PERFSITENT_REF,
569                                                     aComment.toLatin1().data(),
570                                                     true);
571           }
572         }
573       }
574
575       if(!anIsFieldsEntryUpdated && !theIsAtOnce)
576         RemoveSObject(theStudy, aMesh->myFieldsEntry);
577     }
578
579     ProcessVoidEvent(new TUpdateObjBrowser(theStudy->StudyId(),theIsDone));
580   }
581
582
583   //----------------------------------------------------------------------------
584   void
585   BuildMinMax(Result_i* theResult,
586               Result_i::PInput theInput,
587               CORBA::Boolean* theIsDone,
588               CORBA::Boolean theIsBuild)
589   {
590     if(!theIsBuild || *theIsDone)
591       return;
592
593     TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::BuildMinMax");
594     TResultManager aResultManager(theResult);
595     
596     theInput->BuildMinMax();
597
598     *theIsDone = true;
599
600     theResult->UpdateObservers();
601   }
602
603
604   //----------------------------------------------------------------------------
605   void
606   BuildFieldDataTree(Result_i* theResult,
607                      Result_i::PInput theInput,
608                      CORBA::Boolean* theIsFieldsDone,
609                      CORBA::Boolean theIsBuildFields,
610                      CORBA::Boolean* theIsMinMaxDone,
611                      CORBA::Boolean theIsBuildMinMax,
612                      _PTR(Study) theStudy)
613   {
614     BuildFields(theResult,
615                 theInput,
616                 theIsFieldsDone,
617                 theIsBuildFields,
618                 false,
619                 theStudy);
620
621     BuildMinMax(theResult,
622                 theInput,
623                 theIsMinMaxDone,
624                 theIsBuildMinMax);
625   }
626
627
628   //----------------------------------------------------------------------------
629   bool
630   RemoveFile(const std::string& theFileName,
631              bool theRemoveEmptyDir)
632   {
633     QFileInfo aFileInfo(theFileName.c_str());
634     QFile(aFileInfo.absoluteFilePath()).remove();
635     
636     if(theRemoveEmptyDir)
637       QDir().rmdir(aFileInfo.absolutePath());
638
639     return aFileInfo.exists();
640   }
641
642
643   //----------------------------------------------------------------------------
644   bool
645   CopyFile(const std::string& theSourceFileName,
646            const std::string& theTargetFileName)
647   {
648     QString aSourcePath = theSourceFileName.c_str();
649 #ifdef WNT
650     aSourcePath.replace( QString("/"), QString("\\") );
651     int prevSlash = 0;
652     for ( int ind = 0; ind < aSourcePath.length(); ind ++ )
653     {
654       if ( aSourcePath.at( ind ) == '\\' )
655         prevSlash = ind;
656       if ( aSourcePath.at( ind ) == ' ' )
657       {
658         int nextSlash = aSourcePath.indexOf( '\\', ind);
659         if ( aSourcePath.at( nextSlash - 1 ) != '"' )
660         {
661           aSourcePath.insert( nextSlash, '"');
662           aSourcePath.insert( prevSlash + 1, '"');
663           ind++;
664         }
665       }
666     }
667 #endif
668
669     QFileInfo aSourceFileInfo( aSourcePath );
670     QFileInfo aTargetFileInfo( theTargetFileName.c_str() );
671     if(aSourceFileInfo.absoluteFilePath() == aTargetFileInfo.absoluteFilePath())
672       return true;
673
674     QString aCommand;
675     aCommand.sprintf("%s %s %s", COPY_COMMAND,
676                      aSourcePath.toLatin1().data(),
677                      theTargetFileName.c_str());
678
679     return system(aCommand.toLatin1().data()) == 0;
680   }
681
682
683   //----------------------------------------------------------------------------
684 }