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