0028353: Samples - IESample cannot write files to paths with special characters
[occt.git] / samples / qt / Interface / src / Translate.cxx
1 #include "Translate.h"
2
3 #include "Application.h"
4
5 #include <QDir>
6 #include <QLayout>
7 #include <QComboBox>
8 #include <QGroupBox>
9 #include <QList>
10 #include <QListView>
11 #include <QFileDialog>
12 #include <QApplication>
13 #include <QWidget>
14 #include <QStyleFactory>
15
16 #include <AIS_Shape.hxx>
17 #include <AIS_InteractiveObject.hxx>
18
19 #include <IGESControl_Reader.hxx>
20 #include <IGESControl_Writer.hxx>
21 #include <IGESControl_Controller.hxx>
22 #include <STEPControl_Reader.hxx>
23 #include <STEPControl_Writer.hxx>
24 #include <STEPControl_StepModelType.hxx>
25 #include <Interface_Static.hxx>
26 //#include <Interface_TraceFile.hxx>
27
28 #include <StlAPI_Writer.hxx>
29 #include <VrmlAPI_Writer.hxx>
30
31 #include <BRepTools.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRep_Builder.hxx>
34
35 #include <TopoDS.hxx>
36 #include <TopoDS_Shape.hxx>
37 #include <TopoDS_Compound.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopTools_HSequenceOfShape.hxx>
40
41 #include <Geom_Line.hxx>
42 #include <Geom_Curve.hxx>
43 #include <Geom_Plane.hxx>
44 #include <Geom_Surface.hxx>
45
46
47 #include <Standard_ErrorHandler.hxx>
48 #include <Standard_CString.hxx>
49
50 // ---------------------------- TranslateDlg -----------------------------------------
51
52 class TranslateDlg : public QFileDialog
53 {
54 public:
55   TranslateDlg( QWidget* = 0, Qt::WindowFlags flags = 0, bool = true );
56   ~TranslateDlg();
57   int                   getMode() const;
58   void                  setMode( const int );
59   void                  addMode( const int, const QString& );
60   void                  clear();
61
62 protected:
63   void                  showEvent ( QShowEvent* event );
64
65 private:
66   QListView*            findListView( const QObjectList& );
67
68 private:
69   QComboBox*            myBox;
70   QList<int>            myList;
71 };
72
73 TranslateDlg::TranslateDlg( QWidget* parent, Qt::WindowFlags flags, bool modal )
74 : QFileDialog( parent, flags )
75 {
76   setOption( QFileDialog::DontUseNativeDialog );
77   setModal( modal );
78
79   QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
80
81   if( grid )
82   {
83     QVBoxLayout *vbox = new QVBoxLayout;
84  
85     QWidget* paramGroup = new QWidget( this );
86     paramGroup->setLayout( vbox );
87   
88         myBox = new QComboBox( paramGroup );
89     vbox->addWidget( myBox );
90         
91     int row = grid->rowCount();
92     grid->addWidget( paramGroup, row, 1, 1, 3 ); // make combobox occupy 1 row and 3 columns starting from 1
93   }
94 }
95
96 TranslateDlg::~TranslateDlg()
97 {
98 }
99
100 int TranslateDlg::getMode() const
101 {
102   if ( myBox->currentIndex() < 0 || myBox->currentIndex() > (int)myList.count() - 1 )
103     return -1;
104   else
105     return myList.at( myBox->currentIndex() );
106 }
107
108 void TranslateDlg::setMode( const int mode )
109 {
110   int idx = myList.indexOf( mode );
111   if ( idx >= 0 )
112     myBox->setCurrentIndex( idx );
113 }
114
115 void TranslateDlg::addMode( const int mode, const QString& name )
116 {
117   myBox->show();
118         myBox->addItem( name );
119   myList.append( mode );
120   myBox->updateGeometry();
121   updateGeometry();
122 }
123
124 void TranslateDlg::clear()
125 {
126     myList.clear();
127     myBox->clear();
128     myBox->hide();
129     myBox->updateGeometry();
130     updateGeometry();
131 }
132
133 QListView* TranslateDlg::findListView( const QObjectList & childList )
134 {
135   QListView* listView = 0;
136   for ( int i = 0, n = childList.count(); i < n && !listView; i++ )
137   {
138     listView = qobject_cast<QListView*>( childList.at( i ) );
139     if ( !listView && childList.at( i ) )
140     {
141        listView = findListView( childList.at( i )->children() );
142     }
143   }
144   return listView;
145 }
146
147 void TranslateDlg::showEvent ( QShowEvent* event )
148 {
149   QFileDialog::showEvent ( event );
150   QListView* aListView = findListView( children() );
151   aListView->setViewMode( QListView::ListMode );
152 }
153
154
155 // ---------------------------- Translate -----------------------------------------
156
157 Translate::Translate( QObject* parent )
158 : QObject( parent ),
159 myDlg( 0 )
160 {
161 }
162
163 Translate::~Translate()
164 {
165     if ( myDlg )
166         delete myDlg;
167 }
168
169 QString Translate::info() const
170 {
171     return myInfo;
172 }
173
174 bool Translate::importModel( const int format, const Handle(AIS_InteractiveContext)& ic )
175 {
176     myInfo = QString();
177     QString fileName = selectFileName( format, true );
178     if ( fileName.isEmpty() )
179         return true;
180
181     if ( !QFileInfo( fileName ).exists() )
182     {
183         myInfo = QObject::tr( "INF_TRANSLATE_FILENOTFOUND" ).arg( fileName );
184         return false;
185     }
186
187     QApplication::setOverrideCursor( Qt::WaitCursor );
188     Handle(TopTools_HSequenceOfShape) shapes = importModel( format, fileName );
189     QApplication::restoreOverrideCursor();
190
191     return displayShSequence(ic, shapes);
192 }
193
194 bool Translate::displayShSequence(const Handle(AIS_InteractiveContext)& ic,
195                                   const Handle(TopTools_HSequenceOfShape)& shapes )
196 {
197   if ( shapes.IsNull() || !shapes->Length() )
198         return false;
199
200   for ( int i = 1; i <= shapes->Length(); i++ )
201     ic->Display( new AIS_Shape( shapes->Value( i ) ), false );
202   ic->UpdateCurrentViewer();
203   return true;
204 }
205
206 Handle(TopTools_HSequenceOfShape) Translate::importModel( const int format, const QString& file )
207 {
208     Handle(TopTools_HSequenceOfShape) shapes;
209     try {
210         switch ( format )
211         {
212         case FormatBREP:
213             shapes = importBREP( file );
214             break;
215         case FormatIGES:
216             shapes = importIGES( file );
217             break;
218         case FormatSTEP:
219             shapes = importSTEP( file );
220             break;
221         }
222     } catch ( Standard_Failure ) {
223         shapes.Nullify();
224     }
225     return shapes;
226 }
227
228 bool Translate::exportModel( const int format, const Handle(AIS_InteractiveContext)& ic )
229 {
230     myInfo = QString();
231     QString fileName = selectFileName( format, false );
232     if ( fileName.isEmpty() )
233         return true;
234
235     Handle(TopTools_HSequenceOfShape) shapes = getShapes( ic );
236     if ( shapes.IsNull() || !shapes->Length() )
237         return false;
238
239     QApplication::setOverrideCursor( Qt::WaitCursor );
240     bool stat = exportModel( format, fileName, shapes );
241     QApplication::restoreOverrideCursor();
242
243     return stat;
244 }
245
246 bool Translate::exportModel( const int format, const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
247 {
248     bool status;
249     try {
250         switch ( format )
251         {
252         case FormatBREP:
253             status = exportBREP( file, shapes );
254             break;
255         case FormatIGES:
256             status = exportIGES( file, shapes );
257             break;
258         case FormatSTEP:
259             status = exportSTEP( file, shapes );
260             break;
261         case FormatSTL:
262             status = exportSTL( file, shapes );
263             break;
264         case FormatVRML:
265             status = exportVRML( file, shapes );
266             break;
267         }
268     } catch ( Standard_Failure ) {
269         status = false;
270     }
271     return status;
272 }
273
274 Handle(TopTools_HSequenceOfShape) Translate::getShapes( const Handle(AIS_InteractiveContext)& ic )
275 {
276     Handle(TopTools_HSequenceOfShape) aSequence;
277     Handle(AIS_InteractiveObject) picked;
278     for ( ic->InitSelected(); ic->MoreSelected(); ic->NextSelected() )
279     {
280         Handle(AIS_InteractiveObject) obj = ic->SelectedInteractive();
281         if ( obj->IsKind( STANDARD_TYPE( AIS_Shape ) ) )
282         {
283             TopoDS_Shape shape = Handle(AIS_Shape)::DownCast(obj)->Shape();
284             if ( aSequence.IsNull() )
285                 aSequence = new TopTools_HSequenceOfShape();
286             aSequence->Append( shape );
287         }
288     }
289     return aSequence;
290 }
291
292 /*!
293     Selects a file from standard dialog acoording to selection 'filter'
294 */
295 QString Translate::selectFileName( const int format, const bool import )
296 {
297   TranslateDlg* theDlg = getDialog( format, import );
298
299   int ret = theDlg->exec();
300     
301   qApp->processEvents();
302
303   QString file;
304         QStringList fileNames;
305   if ( ret != QDialog::Accepted )
306       return file;
307
308   fileNames = theDlg->selectedFiles();
309         if (!fileNames.isEmpty())
310     file = fileNames[0];
311
312   if ( !QFileInfo( file ).completeSuffix().length() )
313   {
314     QString selFilter = theDlg->selectedNameFilter();
315                 int idx = selFilter.indexOf( "(*." );
316     if ( idx != -1 )
317     {
318       QString tail = selFilter.mid( idx + 3 );
319                         int idx = tail.indexOf( " " );
320       if ( idx == -1 )
321         idx = tail.indexOf( ")" );
322       QString ext = tail.left( idx );
323       if ( ext.length() )
324         file += QString( "." ) + ext;
325     }
326   }
327
328   return file;
329 }
330
331 TranslateDlg* Translate::getDialog( const int format, const bool import )
332 {
333   if ( !myDlg )
334     myDlg = new TranslateDlg( 0, 0, true );
335
336   if ( format < 0 )
337     return myDlg;
338
339   QString formatFilter = QObject::tr( QString( "INF_FILTER_FORMAT_%1" ).arg( format ).toLatin1().constData() );
340   QString allFilter = QObject::tr( "INF_FILTER_FORMAT_ALL" );
341
342   QString filter;
343   filter.append( formatFilter );
344         filter.append( "\t" );
345
346         if ( import ) 
347   {
348     filter.append( allFilter );
349                 filter.append( "\t" );
350         }
351
352   cout << filter.toLatin1().constData() << endl;
353   QStringList filters = filter.split( "\t" );
354   myDlg->setNameFilters ( filters );
355
356         if ( import )
357   {
358           myDlg->setWindowTitle( QObject::tr( "INF_APP_IMPORT" ) );
359     ((QFileDialog*)myDlg)->setFileMode( QFileDialog::ExistingFile );
360   }
361         else
362   {
363           myDlg->setWindowTitle( QObject::tr( "INF_APP_EXPORT" ) );
364     ((QFileDialog*)myDlg)->setFileMode( QFileDialog::AnyFile );
365   }
366
367   myDlg->clear();
368
369   if ( !import )
370   {
371     switch ( format )
372     {
373       case FormatSTEP:
374         myDlg->addMode( STEPControl_ManifoldSolidBrep,      QObject::tr( "INF_BREP_MOIFOLD" ) );
375               myDlg->addMode( STEPControl_FacetedBrep,            QObject::tr( "INF_BREP_FACETED" ) );
376               myDlg->addMode( STEPControl_ShellBasedSurfaceModel, QObject::tr( "INF_BREP_SHELL" ) );
377               myDlg->addMode( STEPControl_GeometricCurveSet,      QObject::tr( "INF_BREP_CURVE" ) );
378         break;
379      }
380   }
381
382   return myDlg;
383 }
384
385 // ----------------------------- Import functionality -----------------------------
386
387 Handle(TopTools_HSequenceOfShape) Translate::importBREP( const QString& file )
388 {
389         Handle(TopTools_HSequenceOfShape) aSequence;
390     TopoDS_Shape aShape;
391         BRep_Builder aBuilder;
392   TCollection_AsciiString  aFilePath = file.toUtf8().data();
393         Standard_Boolean result = BRepTools::Read( aShape, aFilePath.ToCString(), aBuilder );
394         if ( result )
395     {
396             aSequence = new TopTools_HSequenceOfShape();
397                 aSequence->Append( aShape );
398     }
399     return aSequence;
400 }
401
402 Handle(TopTools_HSequenceOfShape) Translate::importIGES( const QString& file )
403 {
404     Handle(TopTools_HSequenceOfShape) aSequence;
405     TCollection_AsciiString  aFilePath = file.toUtf8().data();
406       
407     IGESControl_Reader Reader;
408     int status = Reader.ReadFile(aFilePath.ToCString() );
409
410     if ( status == IFSelect_RetDone )
411     {
412         aSequence = new TopTools_HSequenceOfShape();
413         Reader.TransferRoots();
414         TopoDS_Shape aShape = Reader.OneShape();
415         aSequence->Append( aShape );
416     }
417         return aSequence;
418 }
419
420 Handle(TopTools_HSequenceOfShape) Translate::importSTEP( const QString& file )
421 {
422         Handle(TopTools_HSequenceOfShape) aSequence;
423   TCollection_AsciiString  aFilePath = file.toUtf8().data();
424         STEPControl_Reader aReader;
425         IFSelect_ReturnStatus status = aReader.ReadFile( aFilePath.ToCString() );
426         if ( status == IFSelect_RetDone )
427     {
428             //Interface_TraceFile::SetDefault();
429             bool failsonly = false;
430             aReader.PrintCheckLoad( failsonly, IFSelect_ItemsByEntity );
431
432             int nbr = aReader.NbRootsForTransfer();
433             aReader.PrintCheckTransfer( failsonly, IFSelect_ItemsByEntity );
434             for ( Standard_Integer n = 1; n <= nbr; n++ )
435             {
436                 bool ok = aReader.TransferRoot( n );
437                 int nbs = aReader.NbShapes();
438                 if ( ok == true && nbs > 0 )
439             {
440                     aSequence = new TopTools_HSequenceOfShape();
441                     for ( int i = 1; i <= nbs; i++ )
442                 {
443                             TopoDS_Shape shape = aReader.Shape( i );
444                             aSequence->Append( shape );
445                     }
446             }
447         }
448     }
449         return aSequence;
450 }
451
452 // ----------------------------- Export functionality -----------------------------
453
454 bool Translate::exportBREP( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
455 {
456     if ( shapes.IsNull() || shapes->IsEmpty() )
457         return false;
458
459     TopoDS_Shape shape = shapes->Value( 1 );
460     
461     const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
462     
463     return BRepTools::Write( shape, anUtf8Path.ToCString() ); 
464 }
465
466 bool Translate::exportIGES( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
467 {
468     if ( shapes.IsNull() || shapes->IsEmpty() )
469         return false;
470
471     IGESControl_Controller::Init();
472         IGESControl_Writer writer( Interface_Static::CVal( "XSTEP.iges.unit" ),
473                                Interface_Static::IVal( "XSTEP.iges.writebrep.mode" ) );
474  
475         for ( int i = 1; i <= shapes->Length(); i++ )
476                 writer.AddShape ( shapes->Value( i ) );
477         writer.ComputeModel();
478         
479         const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
480         
481         return writer.Write( anUtf8Path.ToCString() );
482 }
483
484 bool Translate::exportSTEP( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
485 {
486     if ( shapes.IsNull() || shapes->IsEmpty() )
487         return false;
488
489     TranslateDlg* theDlg = getDialog( -1, false );
490     STEPControl_StepModelType type = (STEPControl_StepModelType)theDlg->getMode();
491     if ( type < 0 )
492         return false;
493     
494     IFSelect_ReturnStatus status;
495
496     if ( type == STEPControl_FacetedBrep && !checkFacetedBrep( shapes ) )
497     {
498         myInfo = QObject::tr( "INF_FACET_ERROR" );
499         return false;
500     }
501
502     STEPControl_Writer writer;
503         for ( int i = 1; i <= shapes->Length(); i++ )
504     {
505                 status = writer.Transfer( shapes->Value( i ), type );
506         if ( status != IFSelect_RetDone )
507             return false;
508     }
509     
510     const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
511
512     status = writer.Write( anUtf8Path.ToCString() );
513
514     switch ( status )
515     {
516     case IFSelect_RetError:
517         myInfo = QObject::tr( "INF_DATA_ERROR" );
518         break;
519     case IFSelect_RetFail:
520         myInfo = QObject::tr( "INF_WRITING_ERROR" );
521         break;
522     case IFSelect_RetVoid:
523         myInfo = QObject::tr( "INF_NOTHING_ERROR" );
524         break;
525     }
526     return status == IFSelect_RetDone;
527 }
528
529 bool Translate::exportSTL( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
530 {
531     if ( shapes.IsNull() || shapes->IsEmpty() )
532         return false;
533
534         TopoDS_Compound res;
535         BRep_Builder builder;
536         builder.MakeCompound( res );
537
538         for ( int i = 1; i <= shapes->Length(); i++ )
539         {
540                 TopoDS_Shape shape = shapes->Value( i );
541                 if ( shape.IsNull() ) 
542                 {
543                         myInfo = QObject::tr( "INF_TRANSLATE_ERROR_INVALIDSHAPE" );
544                         return false;
545         }
546                 builder.Add( res, shape );
547         }
548
549         StlAPI_Writer writer;
550         
551         const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
552         
553         writer.Write( res, anUtf8Path.ToCString() );
554
555     return true;
556 }
557
558 bool Translate::exportVRML( const QString& file, const Handle(TopTools_HSequenceOfShape)& shapes )
559 {
560     if ( shapes.IsNull() || shapes->IsEmpty() )
561         return false;
562
563         TopoDS_Compound res;
564         BRep_Builder builder;
565         builder.MakeCompound( res );
566
567         for ( int i = 1; i <= shapes->Length(); i++ )
568         {
569                 TopoDS_Shape shape = shapes->Value( i );
570                 if ( shape.IsNull() )
571                 {
572                         myInfo = QObject::tr( "INF_TRANSLATE_ERROR_INVALIDSHAPE" );
573                         return false;
574         }
575                 builder.Add( res, shape );
576         }
577
578         VrmlAPI_Writer writer;
579         
580         const TCollection_AsciiString anUtf8Path (file.toUtf8().data());
581         
582         writer.Write( res, anUtf8Path.ToCString() );
583
584     return true;
585 }
586
587 bool Translate::checkFacetedBrep( const Handle(TopTools_HSequenceOfShape)& shapes )
588 {
589         bool err = false;
590         for ( int i = 1; i <= shapes->Length(); i++ )
591         {
592             TopoDS_Shape shape = shapes->Value( i );
593         for ( TopExp_Explorer fexp( shape, TopAbs_FACE ); fexp.More() && !err; fexp.Next() )
594                 {
595                     Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face( fexp.Current() ) );
596                     if ( !surface->IsKind( STANDARD_TYPE( Geom_Plane ) ) )
597                         err = true;
598                 }
599         for ( TopExp_Explorer eexp( shape, TopAbs_EDGE ); eexp.More() && !err; eexp.Next() )
600                 {
601                     Standard_Real fd, ld;
602                     Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( eexp.Current() ), fd, ld );
603                     if ( !curve->IsKind( STANDARD_TYPE( Geom_Line ) ) )
604                         err = true;
605                 }
606         }
607         return !err;
608 }
609
610
611