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