Salome HOME
e64e65d8b635fa5be0367443b66c1faec094aeb1
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_SelectionProxy.cxx
1 // Copyright (C) 2007-2016  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, or (at your option) any later version.
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 #include "SMESHGUI_SelectionProxy.h"
24
25 #include "SMESHGUI.h"
26 #include "SMESHGUI_Utils.h"
27 #include "SMESHGUI_VTKUtils.h"
28 #include "SMESH_Actor.h"
29
30 #include <SALOMEconfig.h>
31 #include CORBA_SERVER_HEADER(SMESH_Group)
32
33 #include <SALOMEDSClient_Study.hxx>
34 #include <SUIT_ResourceMgr.h>
35
36 ////////////////////////////////////////////////////////////////////////////////
37 /// \class SMESHGUI_SelectionProxy
38 /// \brief Provide operations over the selected object.
39 ///
40 /// The selection proxy class is aimed to use in dialogs to access mesh object
41 /// data either from actor or directly from CORBA reference, depending on what
42 /// of them is accessible.
43 /// This is useful in situations when some information is needed, but an actor
44 /// was not created yet.
45 /// 
46 /// Selection proxy can be constructed in two ways:
47 /// - From interactive object: this performs full proxy initialization including
48 ///   pick-up of an actor from the current viewer if it exists.
49 /// - From mesh source object (CORBA reference); for performance reasons in this
50 ///   case full initialization is not immediately done and performed only when
51 ///   needed.
52 ////////////////////////////////////////////////////////////////////////////////
53
54 /*!
55   \brief Default constructor. Creates null proxy.
56 */
57 SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy(): myActor(0), myDirty(false)
58 {
59 }
60
61 /*!
62   \brief Constructor.
63   \param io Interactive object.
64 */
65 SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( const Handle(SALOME_InteractiveObject)& io ): myActor(0), myDirty(true)
66 {
67   myObject = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( io );
68   init();
69 }
70
71 /*!
72   \brief Constructor.
73   \param object Mesh source.
74 */
75 SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( SMESH::SMESH_IDSource_ptr object ): myActor(0), myDirty(true)
76 {
77   if ( !CORBA::is_nil( object ) )
78     myObject = SMESH::SMESH_IDSource::_duplicate( object );
79 }
80
81 /*!
82   \brief Copy constructor.
83   \param other Proxy being copied.
84 */
85 SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( const SMESHGUI_SelectionProxy& other )
86 {
87   myIO = other.myIO;
88   myObject = other.myObject;
89   myActor = other.myActor;
90   myDirty = other.myDirty;
91 }
92
93 /*!
94   \brief Perform internal initialization.
95   \internal
96 */
97 void SMESHGUI_SelectionProxy::init()
98 {
99   if ( myIO.IsNull() )
100     myIO = new SALOME_InteractiveObject(); // create dummy IO to avoid crashes when accesing it
101
102   if ( !CORBA::is_nil( myObject ) )
103   {
104     if ( !myIO->hasEntry() )
105     {
106       _PTR(SObject) sobj = SMESH::ObjectToSObject( myObject.in() );
107       if ( sobj )
108         myIO = new SALOME_InteractiveObject( sobj->GetID().c_str(), "SMESH", sobj->GetName().c_str() );
109     }
110     if ( !myActor && myIO->hasEntry() )
111       myActor = SMESH::FindActorByEntry( myIO->getEntry() );
112   }
113   myDirty = false;
114 }
115
116 /*!
117   \brief Assignment operator.
118   \param other Proxy being copied.
119 */
120 SMESHGUI_SelectionProxy& SMESHGUI_SelectionProxy::operator= ( const SMESHGUI_SelectionProxy& other )
121 {
122   myIO = other.myIO;
123   myObject = other.myObject;
124   myActor = other.myActor;
125   myDirty = other.myDirty;
126   return *this;
127 }
128
129 /*!
130   \brief Equality comparison operator.
131   \param other Proxy to compare with.
132   \return \c true if two proxies are equal; \c false otherwise.
133 */
134 bool SMESHGUI_SelectionProxy::operator== ( const SMESHGUI_SelectionProxy& other )
135 {
136   return !CORBA::is_nil( myObject ) && !CORBA::is_nil( other.myObject ) && 
137     myObject->_is_equivalent( other.myObject );
138 }
139
140 /*!
141   \brief Try to re-initialize proxy.
142 */
143 void SMESHGUI_SelectionProxy::refresh()
144 {
145   init();
146 }
147
148 /*!
149   \brief Check if proxy is null.
150   \return \c true if proxy is null; \c false otherwise.
151 */
152 bool SMESHGUI_SelectionProxy::isNull() const
153 {
154   return CORBA::is_nil( myObject );
155 }
156
157 /*!
158   \brief Boolean conversion operator.
159   \return \c true if proxy is not null; \c false otherwise.
160 */
161 SMESHGUI_SelectionProxy::operator bool() const
162 {
163   return !isNull();
164 }
165
166 /*!
167   \brief Get interactive object.
168   \return Interactive object referenced by proxy.
169 */
170 const Handle(SALOME_InteractiveObject)& SMESHGUI_SelectionProxy::io() const
171 {
172   if ( myDirty )
173     const_cast<SMESHGUI_SelectionProxy*>(this)->init();
174   return myIO;
175 }
176
177 /*!
178   \brief Get mesh object.
179   \return Mesh object (mesh, sub-mesh, group, etc.) referenced by proxy.
180 */
181 SMESH::SMESH_IDSource_ptr SMESHGUI_SelectionProxy::object() const
182 {
183   return SMESH::SMESH_IDSource::_duplicate( myObject );
184 }
185
186 /*!
187   \brief Get actor.
188   \return Actor referenced by proxy.
189 */
190 SMESH_Actor* SMESHGUI_SelectionProxy::actor() const
191 {
192   if ( myDirty )
193     const_cast<SMESHGUI_SelectionProxy*>(this)->init();
194   return myActor;
195 }
196
197 /*!
198   \brief Get object's validity.
199
200   Mesh object is valid if it is null and information stored in it is valid.
201
202   \return \c true if object is valid; \c false otherwise.
203 */
204 bool SMESHGUI_SelectionProxy::isValid() const
205 {
206   return !isNull() && myObject->IsMeshInfoCorrect();
207 }
208
209 /*!
210   \brief Load mesh object from study file.
211 */
212 void SMESHGUI_SelectionProxy::load()
213 {
214   if ( !isNull() )
215   {
216     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
217     if ( !CORBA::is_nil( mesh ) )
218       mesh->Load();
219   }
220 }
221
222 /*!
223   \brief Get name.
224   \return Mesh object's name.
225 */
226 QString SMESHGUI_SelectionProxy::name() const
227 {
228   QString value;
229   if ( !isNull() )
230     value = io()->getName();
231   return value;
232 }
233
234 /*!
235   \brief Get type.
236   \return Mesh object's type.
237 */
238 SMESHGUI_SelectionProxy::Type SMESHGUI_SelectionProxy::type() const
239 {
240   Type value = Unknown;
241   if ( !isNull() )
242   {
243     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
244     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( myObject );
245     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
246     SMESH::SMESH_Group_var sGroup = SMESH::SMESH_Group::_narrow( myObject );
247     SMESH::SMESH_GroupOnGeom_var gGroup = SMESH::SMESH_GroupOnGeom::_narrow( myObject );
248     SMESH::SMESH_GroupOnFilter_var fGroup = SMESH::SMESH_GroupOnFilter::_narrow( myObject );
249     
250     if ( !CORBA::is_nil( mesh ) )
251       value = Mesh;
252     else if ( !CORBA::is_nil( submesh ) )
253       value = Submesh;
254     else if ( !CORBA::is_nil( sGroup ) )
255       value = GroupStd;
256     else if ( !CORBA::is_nil( gGroup ) )
257       value = GroupGeom;
258     else if ( !CORBA::is_nil( fGroup ) )
259       value = GroupFilter;
260     else if ( !CORBA::is_nil( group ) )
261       value = Group;
262   }
263   return value;
264 }
265
266 /*!
267   \brief Get mesh information.
268   \return Statistics on stored mesh object.
269 */
270 SMESHGUI_MeshInfo SMESHGUI_SelectionProxy::meshInfo() const
271 {
272   SMESHGUI_MeshInfo info;
273   if ( !isNull() )
274   {
275     SMESH::long_array_var data = myObject->GetMeshInfo();
276     for ( uint type = SMESH::Entity_Node; type < SMESH::Entity_Last; type++ )
277     {
278       if ( type < data->length() )
279         info.addInfo( type, data[ type ] );
280     }
281   }
282   return info;
283 }
284
285 /*!
286   \brief Get parent mesh.
287   \return Proxy object that stores parent mesh object.
288   \note For proxy that stores a mesh, returns its copy.
289 */
290 SMESHGUI_SelectionProxy SMESHGUI_SelectionProxy::mesh() const
291 {
292   SMESHGUI_SelectionProxy parent;
293   if ( isValid() )
294     parent = SMESHGUI_SelectionProxy( (SMESH::SMESH_Mesh_var) myObject->GetMesh() ); // cast to var to avoid leaks
295   return parent;
296 }
297
298 /*!
299   \brief Check if parent mesh has shape to mesh.
300   \return \c true if Parent mesh is built on a shape; \c false otherwise.
301   \note For group or submesh, this method checks that parent mesh has a shape.
302 */
303 bool SMESHGUI_SelectionProxy::hasShapeToMesh() const
304 {
305   bool result = false;
306   if ( !isNull() )
307   {
308     SMESHGUI_SelectionProxy parent = mesh();
309     if ( parent )
310     {
311       SMESH::SMESH_Mesh_var m = SMESH::SMESH_Mesh::_narrow( (SMESH::SMESH_IDSource_var)parent.object() ); // cast to var to avoid leaks
312       result = m->HasShapeToMesh();
313     }
314   }
315   return result;
316 }
317
318 /*!
319   \brief Get referenced GEOM object.
320   \return GEOM object referenced by selection proxy.
321
322   The result contains valid pointer only if proxy refers to mesh, sub-mesh
323   or group created on a geometry.
324 */
325 GEOM::GEOM_Object_ptr SMESHGUI_SelectionProxy::shape() const
326 {
327   GEOM::GEOM_Object_var shape;
328   if ( !isNull() )
329   {
330     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
331     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( myObject );
332     SMESH::SMESH_GroupOnGeom_var group = SMESH::SMESH_GroupOnGeom::_narrow( myObject );
333     if ( !CORBA::is_nil( mesh ) )
334       shape = mesh->GetShapeToMesh();
335     else if ( !CORBA::is_nil( submesh ) )
336       shape = submesh->GetSubShape();
337     else if ( !CORBA::is_nil( group ) )
338       shape = group->GetShape();
339   }
340   return shape._retn();
341 }
342
343 /*!
344   \brief Get name of referenced GEOM object.
345   \return Name of GEOM object referenced by selection proxy.
346
347   The result contains non-empty name only if proxy refers to mesh, sub-mesh
348   or group created on a geometry, and if that geometry has valid name.
349 */
350 QString SMESHGUI_SelectionProxy::shapeName() const
351 {
352   QString name;
353   if ( !isNull() )
354   {
355     GEOM::GEOM_Object_var gobj = shape();
356     _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
357     if ( sobj )
358       name = QString::fromStdString( sobj->GetName() );
359   }
360   return name;
361 }
362
363 /*!
364   \brief Get type of referenced GEOM object.
365   \return Type of GEOM object referenced by selection proxy.
366
367   The result contains valid type only if proxy refers to mesh, sub-mesh
368   or group created on a geometry.
369 */
370 int SMESHGUI_SelectionProxy::shapeType() const
371 {
372   int type = -1;
373   if ( !isNull() )
374   {
375     GEOM::GEOM_Object_var gobj = shape();
376     if ( !CORBA::is_nil( gobj ) )
377       type = gobj->GetShapeType();
378   }
379   return type;
380 }
381
382 /*!
383   \brief Check if mesh has been loaded from study file.
384   \return \c true if mesh was loaded; \c false otherwise.
385 */
386 bool SMESHGUI_SelectionProxy::isMeshLoaded() const
387 {
388   bool result = true; // set default to true to avoid side effects
389   if ( isValid() )
390   {
391     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
392     if ( !CORBA::is_nil( mesh ) )
393       result = mesh->IsLoaded();
394   }
395   return result;
396 }
397
398 /*!
399   \brief Get MED file information.
400   \return MED file information.
401
402   The result contains valid data only if proxy refers to mesh object
403   which has been imported from the MED file.
404 */
405 SMESHGUI_MedFileInfo SMESHGUI_SelectionProxy::medFileInfo() const
406 {
407   SMESHGUI_MedFileInfo info;
408   if ( !isNull() )
409   {
410     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
411     if ( !CORBA::is_nil( mesh ) )
412     {
413       SMESH::MedFileInfo_var inf = mesh->GetMEDFileInfo();
414       info.setFileName( inf->fileName.in() );
415       info.setSize( inf->fileSize );
416       info.setVersion( inf->major, inf->minor, inf->release );
417     }
418   }
419   return info;
420 }
421
422 /*!
423   \brief Get child sub-meshes.
424   \return List of sub-meshes for mesh object; empty list for other types.
425 */
426 QList<SMESHGUI_SelectionProxy> SMESHGUI_SelectionProxy::submeshes() const
427 {
428   QList<SMESHGUI_SelectionProxy> lst;
429   if ( !isNull() )
430   {
431     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
432     if ( !CORBA::is_nil( mesh ) )
433     {
434       SMESH::submesh_array_var array = mesh->GetSubMeshes();
435       for ( uint i = 0 ; i < array->length(); i++ )
436         lst << SMESHGUI_SelectionProxy( array[i].in() );
437     }
438   }
439   return lst;
440 }
441
442 /*!
443   \brief Get child groups.
444   \return List of groups for mesh object; empty list for other types.
445 */
446 QList<SMESHGUI_SelectionProxy> SMESHGUI_SelectionProxy::groups() const
447 {
448   QList<SMESHGUI_SelectionProxy> lst;
449   if ( !isNull() )
450   {
451     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
452     if ( !CORBA::is_nil( mesh ) )
453     {
454       SMESH::ListOfGroups_var array = mesh->GetGroups();
455       for ( uint i = 0 ; i < array->length(); i++ )
456         lst << SMESHGUI_SelectionProxy( array[i].in() );
457     }
458   }
459   return lst;
460 }
461
462 /*!
463   \brief Get element type (for group). For other mesh objects result is undefined.
464   \return Group's element type.
465 */
466 SMESH::ElementType SMESHGUI_SelectionProxy::elementType() const
467 {
468   SMESH::ElementType value = SMESH::ALL;
469   if ( !isNull() )
470   {
471     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
472     if ( !CORBA::is_nil( group ) )
473       value = group->GetType();
474   }
475   return value;
476 }
477
478 /*!
479   \brief Get color (for group). For other mesh objects result is undefined.
480   \return Group's color.
481 */
482 QColor SMESHGUI_SelectionProxy::color() const
483 {
484   QColor result;
485   if ( !isNull() )
486   {
487     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
488     if ( !CORBA::is_nil( group ) )
489     {
490       SALOMEDS::Color c = group->GetColor();
491       result = QColor::fromRgbF( c.R, c.G, c.B );
492     }
493   }
494   return result;
495 }
496
497 /*!
498   \brief Get size (for group). For other mesh objects result is undefined.
499   \param autoCompute Compute size if it is unavailable. Defaults to \c false.
500   \return Group's size.
501 */
502 int SMESHGUI_SelectionProxy::size( bool autoCompute ) const
503 {
504   // note: size is not computed for group on filter for performance reasons, see IPAL52831
505   int result = -1;
506   if ( !isNull() )
507   {
508     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
509     if ( !CORBA::is_nil( group ) )
510     {
511       if ( type() == GroupFilter )
512         // for group on filter we check if value is already computed and cached
513         autoCompute |= group->IsNodeInfoAvailable();
514       else
515         // for other groups we force autoCompute to true
516         autoCompute = true;
517       if ( autoCompute )
518         result = group->Size();
519     }
520   }
521   return result;
522 }
523
524 /*!
525   \brief Get number of underlying nodes (for group of elements). For other
526   mesh objects result is undefined.
527   \param autoCompute Compute size if it is unavailable. Defaults to \c false.
528   \return Number of nodes contained in group.
529 */
530 int SMESHGUI_SelectionProxy::nbNodes( bool autoCompute ) const
531 {
532   // note: nb of nodes is not computed automatically for performance reasons
533   int result = -1;
534   if ( !isNull() )
535   {
536     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
537     if ( !CORBA::is_nil( group ) && ( autoCompute || isMeshLoaded() ) )
538     {
539       int groupSize = size( autoCompute );
540       if ( groupSize >= 0 )
541       {
542         int limit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
543         if ( group->IsNodeInfoAvailable() || limit <= 0 || groupSize <= limit )
544           result = group->GetNumberOfNodes();
545       }
546     }
547   }
548   return result;
549 }
550
551 /*!
552   \brief Get list of nodes / elements IDs for the mesh group.
553   \return List of IDs for group object; empty list for other types.
554 */
555 QSet<uint> SMESHGUI_SelectionProxy::ids() const
556 {
557   QSet<uint> result;
558   if ( !isNull() )
559   {
560     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( myObject );
561     if ( !CORBA::is_nil( group ) )
562     {
563       SMESH::long_array_var seq = group->GetListOfID();
564       for ( int i = 0, n = seq->length(); i < n; i++ )
565         result << (uint)seq[i];
566     }
567   }
568   return result;
569 }
570
571 ////////////////////////////////////////////////////////////////////////////////
572 /// \class SMESHGUI_MeshInfo
573 /// \brief Store statistics on mesh object.
574 ////////////////////////////////////////////////////////////////////////////////
575
576 /*!
577   \brief Constructor.
578 */
579 SMESHGUI_MeshInfo::SMESHGUI_MeshInfo()
580 {
581 }
582
583 /*!
584   \brief Add information on given entity type.
585   \param type Entity type.
586   \param value Number of entities.
587 */
588 void SMESHGUI_MeshInfo::addInfo( int type, long value )
589 {
590   myInfo[type] = value;
591 }
592
593 /*!
594   \brief Get number of entities of given type.
595   \param type Entity type.
596   \return Number of entities.
597 */
598 uint SMESHGUI_MeshInfo::info( int type ) const
599 {
600   return myInfo.value( type, 0U );
601 }
602
603 /*!
604   \brief Access operator.
605   \param type Entity type.
606   \return Number of entities.
607 */
608 uint SMESHGUI_MeshInfo::operator[] ( int type )
609 {
610   return (uint)info( type );
611 }
612
613 /*!
614   \brief Get total number of entities for types in given range.
615   \param fromType Lower entity type.
616   \param toType Upper entity type.
617   \return Number of entities.
618 */
619 uint SMESHGUI_MeshInfo::count( int fromType, int toType ) const
620 {
621   uint value = 0;
622   for ( int type = fromType; type <= toType; type++ )
623     value += info( type );
624   return value;
625 }
626
627 ////////////////////////////////////////////////////////////////////////////////
628 /// \class SMESHGUI_MedFileInfo
629 /// \brief Provide operations over the selected object
630 ////////////////////////////////////////////////////////////////////////////////
631
632 /*!
633   \brief Constructor.
634 */
635 SMESHGUI_MedFileInfo::SMESHGUI_MedFileInfo()
636 {
637 }
638
639 /*!
640   \brief Get validity status.
641
642   MED file information is valid if at least stored file name is not null.
643
644   \return \c true if MED file info is valid; \c false otherwise.
645 */
646 bool SMESHGUI_MedFileInfo::isValid() const
647 {
648   return !myFileName.isEmpty();
649 }
650
651 /*!
652   \brief Get file name for mesh imported from MED file.
653   \return MED file name.
654 */
655 QString SMESHGUI_MedFileInfo::fileName() const
656 {
657   return myFileName;
658 }
659
660 /*!
661   \brief Set file name for mesh imported from MED file.
662   \param fileName MED file name.
663 */
664 void SMESHGUI_MedFileInfo::setFileName( const QString& fileName )
665 {
666   myFileName = fileName;
667 }
668
669 /*!
670   \brief Get file size for mesh imported from MED file.
671   \return MED file size.
672 */
673 uint SMESHGUI_MedFileInfo::size() const
674 {
675   return mySize;
676 }
677
678 /*!
679   \brief Set file size for mesh imported from MED file.
680   \param size MED file size.
681 */
682 void SMESHGUI_MedFileInfo::setSize( uint size )
683 {
684   mySize = size;
685 }
686
687 /*!
688   \brief Get version of format for mesh imported from MED file.
689   \return MED file format version.
690 */
691 QString SMESHGUI_MedFileInfo::version() const
692 {
693   QString v = QString( "%1" ).arg( myMajor );
694   if ( myMinor > 0 || myRelease > 0 ) v += QString( ".%1" ).arg( myMinor );
695   else if ( myMajor > 0 ) v += ".0";
696   if ( myRelease > 0 ) v += QString( ".%1" ).arg( myRelease );
697   return v;
698 }
699
700 /*!
701   \brief Set version of format for mesh imported from MED file.
702   \param major Major version number.
703   \param minor Minor version number.
704   \param release Release version number.
705 */
706 void SMESHGUI_MedFileInfo::setVersion( uint major, uint minor, uint release )
707 {
708   myMajor = major;
709   myMinor = minor;
710   myRelease = release;
711 }