Salome HOME
Merge from V6_main 01/04/2013
[modules/gui.git] / src / LightApp / LightApp_SelectionMgr.cxx
1 // Copyright (C) 2007-2013  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
23 #include "LightApp_SelectionMgr.h"
24
25 #include "LightApp_Study.h"
26 #include "LightApp_DataOwner.h"
27 #include "LightApp_DataSubOwner.h"
28 #include "LightApp_Application.h"
29
30 #include <SUIT_Session.h>
31 #include <SUIT_Selector.h>
32
33 #ifndef DISABLE_SALOMEOBJECT
34   #include <SALOME_ListIO.hxx>
35   #include <SALOME_ListIteratorOfListIO.hxx>
36
37   // Open CASCADE Include
38   #include <TColStd_MapOfInteger.hxx>
39   #include <TColStd_MapIteratorOfMapOfInteger.hxx>
40   #include <TColStd_IndexedMapOfInteger.hxx>
41   #include <TCollection_AsciiString.hxx>
42 #endif
43
44 #include <QtCore/QSet>
45
46 /*!
47   Constructor.
48 */
49 LightApp_SelectionMgr::LightApp_SelectionMgr( LightApp_Application* app, const bool fb )
50 : SUIT_SelectionMgr( fb ),
51   myApp( app ),
52   myTimeStamp( QTime::currentTime() ),
53   myCacheState( false )
54 {
55 }
56
57 /*!
58   Destructor.
59 */
60 LightApp_SelectionMgr::~LightApp_SelectionMgr()
61 {
62 }
63
64 /*!
65   Gets application.
66 */
67 LightApp_Application* LightApp_SelectionMgr::application() const
68 {
69   return myApp;
70 }
71
72 void LightApp_SelectionMgr::setSelected( const SUIT_DataOwnerPtrList& lst, const bool append )
73 {
74   SUIT_SelectionMgr::setSelected( lst, append );
75
76   myTimeStamp = QTime::currentTime();
77 }
78
79 #ifndef DISABLE_SALOMEOBJECT
80 /*!
81   Get all selected objects from selection manager
82 */
83 void LightApp_SelectionMgr::selectedObjects( SALOME_ListIO& theList, const QString& theType,
84                                              const bool convertReferences ) const
85 {
86   LightApp_Study* study = dynamic_cast<LightApp_Study*>( application()->activeStudy() );
87   if ( !study )
88     return;
89   
90   theList.Clear();
91
92   QList<Handle(SALOME_InteractiveObject)> selList;
93
94   if ( isActualSelectionCache( theType ) ) {
95     selList = selectionCache( theType );
96   }
97   else {
98     QStringList types;
99     if ( !theType.isEmpty() )
100       types.append( theType );
101     else
102       types = selectorTypes();
103
104     QSet<QString> aSet;
105     for ( QStringList::iterator it = types.begin(); it != types.end(); ++it ) {
106       SUIT_DataOwnerPtrList aList;
107       selected( aList, *it );
108
109       QList<Handle(SALOME_InteractiveObject)> typeSelList;
110
111       for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr ) {
112         const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr).operator->() );
113         if ( !owner )
114           continue;
115
116         if ( !aSet.contains( owner->entry() ) ) {
117           selList.append( owner->IO() );
118           aSet.insert( owner->entry() );
119         }
120
121         typeSelList.append( owner->IO() );
122       }
123
124       if ( isSelectionCacheEnabled() ) {
125         LightApp_SelectionMgr* that = (LightApp_SelectionMgr*)this;
126         that->myCacheSelection.insert( *it, typeSelList );
127         that->myCacheTimes.insert( *it, QTime::currentTime() );
128       }
129     }
130   }
131
132   QSet<QString> entrySet;
133   for ( QList<Handle(SALOME_InteractiveObject)>::const_iterator itr = selList.begin(); itr != selList.end(); ++itr )
134   {
135     Handle(SALOME_InteractiveObject) io = *itr;
136     QString entry( io->getEntry() );
137     // Entry to check object uniqueness.
138     // It is selected owner entry in the case, when we do not convert references,
139     // and entry of a real object, when we convert references.
140     if ( convertReferences ) {
141       QString refEntry = study->referencedToEntry( entry );
142       if ( !entrySet.contains( refEntry ) ) {
143         if ( refEntry != entry ) {
144           entry = refEntry;
145           QString component = study->componentDataType( entry );
146           theList.Append( new SALOME_InteractiveObject( (const char*)entry.toLatin1(),
147                                                         (const char*)component.toLatin1(),
148                                                         ""/*refobj->Name().c_str()*/ ) );
149         }
150         else if ( !io.IsNull() )
151           theList.Append( io );
152       }
153     }
154     else if ( !entrySet.contains( entry ) && !io.IsNull() )
155       theList.Append( io );
156
157     entrySet.insert( entry );
158   }
159 }
160
161 /*!
162   Append selected objects.
163 */
164 void LightApp_SelectionMgr::setSelectedObjects( const SALOME_ListIO& lst, const bool append )
165 {
166   SUIT_DataOwnerPtrList owners;
167   for ( SALOME_ListIteratorOfListIO it( lst ); it.More(); it.Next() )
168   {
169     if ( it.Value()->hasEntry() )
170       owners.append( new LightApp_DataOwner( it.Value() ) );
171   }
172
173   setSelected( owners, append );
174 }
175
176 #else
177 /*!
178   Get all selected objects from selection manager
179 */
180 void LightApp_SelectionMgr::selectedObjects( QStringList& theList, const QString& theType,
181                                              const bool convertReferences ) const
182 {
183   LightApp_Study* study = dynamic_cast<LightApp_Study*>( application()->activeStudy() );
184   if ( !study )
185     return;
186
187   theList.clear();
188
189   QStringList selList;
190
191   if ( isActualSelectionCache( theType ) )
192     selList = selectionCache( theType );
193   else {
194     QStringList types;
195     if ( !theType.isEmpty() )
196       types.append( theType );
197     else
198       types = selectorTypes();
199
200     QSet<QString> aSet;
201     for ( QStringList::iterator it = types.begin(); it != types.end(); ++it ) {
202       SUIT_DataOwnerPtrList aList;
203       selected( aList, *it );
204
205       QStringList typeSelList;
206
207       for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr ) {
208         const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr).operator->() );
209         if ( !owner )
210           continue;
211
212         if ( !aSet.contains( owner->entry() ) ) {
213           selList.append( owner->entry() );
214           aSet.insert( owner->entry() );
215         }
216
217         typeSelList.append( owner->entry() );
218       }
219
220       if ( isSelectionCacheEnabled() ) {
221         LightApp_SelectionMgr* that = (LightApp_SelectionMgr*)this;
222         that->myCacheSelection.insert( *it, typeSelList );
223         that->myCacheTimes.insert( *it, QTime::currentTime() );
224       }
225     }
226   }
227
228   theList = selList;
229 }
230
231 #endif
232
233 /*!
234   Emit current selection changed.
235 */
236 void LightApp_SelectionMgr::selectionChanged( SUIT_Selector* theSel )
237 {
238   SUIT_SelectionMgr::selectionChanged( theSel );
239
240   myTimeStamp = QTime::currentTime();
241
242   emit currentSelectionChanged();
243 }
244
245 #ifndef DISABLE_SALOMEOBJECT
246
247 /*!
248   get map of indexes for the given SALOME_InteractiveObject
249 */
250 void LightApp_SelectionMgr::GetIndexes( const Handle(SALOME_InteractiveObject)& IObject,
251                                         TColStd_IndexedMapOfInteger& theIndex)
252 {
253   theIndex.Clear();
254
255   SUIT_DataOwnerPtrList aList;
256   selected( aList );
257
258   for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
259   {
260     LightApp_DataSubOwner* subOwner = dynamic_cast<LightApp_DataSubOwner*>( (*itr).operator->() );
261     if ( subOwner && subOwner->entry() == QString(IObject->getEntry()) )
262       theIndex.Add( subOwner->index() );
263   }
264 }
265
266 /*!
267   get map of indexes for the given entry of SALOME_InteractiveObject
268 */
269 void LightApp_SelectionMgr::GetIndexes( const QString& theEntry, TColStd_IndexedMapOfInteger& theIndex )
270 {
271   theIndex.Clear();
272
273   SUIT_DataOwnerPtrList aList;
274   selected( aList );
275
276   for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
277   {
278     const LightApp_DataSubOwner* subOwner = dynamic_cast<const LightApp_DataSubOwner*>( (*itr).operator->() );
279     if ( subOwner )
280       if ( subOwner->entry() == theEntry )
281         theIndex.Add( subOwner->index() );
282   }
283
284 }
285
286 /*!
287   Add or remove interactive objects from selection manager.
288 */
289 //bool LightApp_SelectionMgr::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& IObject,
290 void LightApp_SelectionMgr::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& IObject,
291                                               const TColStd_MapOfInteger& theIndexes,
292                                               bool modeShift)
293 {
294   SUIT_DataOwnerPtrList remainsOwners;
295
296   SUIT_DataOwnerPtrList aList;
297   selected( aList );
298
299   QString ioEntry (IObject->getEntry());
300
301   if ( !modeShift ) {
302     for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
303     {
304       const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr).operator->() );
305       if ( owner )
306       {
307         if ( owner->entry() != ioEntry )
308         {
309           const LightApp_DataSubOwner* subOwner = dynamic_cast<const LightApp_DataSubOwner*>( owner );
310           if ( subOwner )
311             remainsOwners.append( new LightApp_DataSubOwner( subOwner->entry(), subOwner->index() ) );
312           else
313             remainsOwners.append( new LightApp_DataOwner( owner->entry() ) );
314         }
315       }
316     }
317   }
318   else
319     remainsOwners = aList;
320
321   TColStd_MapIteratorOfMapOfInteger It;
322   It.Initialize(theIndexes);
323   for(;It.More();It.Next())
324     remainsOwners.append( new LightApp_DataSubOwner( ioEntry, It.Key() ) );
325
326   bool append = false;
327   setSelected( remainsOwners, append );
328
329   emit currentSelectionChanged();
330
331   // Bug 17269: To avoid calling of selected(aList)
332   //TColStd_IndexedMapOfInteger anIndexes;
333   //GetIndexes( IObject, anIndexes );
334   //return !anIndexes.IsEmpty();
335 }
336
337 /*!
338   select 'subobjects' with given indexes
339 */
340 void LightApp_SelectionMgr::selectObjects( const Handle(SALOME_InteractiveObject)& IObject,
341                                             TColStd_IndexedMapOfInteger theIndex, bool append )
342 {
343   SUIT_DataOwnerPtrList aList;
344
345   if ( theIndex.IsEmpty() )
346     aList.append( new LightApp_DataOwner( QString(IObject->getEntry()) ) );
347   else
348     {
349       int i;
350       for ( i = 1; i <= theIndex.Extent(); i++ )
351         aList.append( new LightApp_DataSubOwner( QString(IObject->getEntry()), theIndex( i ) ) );
352     }
353
354   setSelected( aList, append );
355 }
356
357 /*!
358   select 'subobjects' with given indexes
359 */
360 void LightApp_SelectionMgr::selectObjects( MapIOOfMapOfInteger theMapIO, bool append )
361 {
362   SUIT_DataOwnerPtrList aList;
363
364   MapIOOfMapOfInteger::Iterator it(theMapIO);
365   for ( ; it.More(); it.Next() )
366     {
367       if ( it.Value().IsEmpty() )
368         aList.append( new LightApp_DataOwner( QString(it.Key()->getEntry()) ) );
369       else
370         {
371           int i;
372           for ( i = 1; i <= it.Value().Extent(); i++ )
373             aList.append( new LightApp_DataSubOwner( QString(it.Key()->getEntry()), it.Value()( i ) ) );
374         }
375     }
376
377   setSelected( aList, append );
378 }
379
380 /*!
381   get map of selected subowners : object's entry <-> map of indexes
382 */
383 void LightApp_SelectionMgr::selectedSubOwners( MapEntryOfMapOfInteger& theMap )
384 {
385   theMap.Clear();
386
387   TColStd_IndexedMapOfInteger anIndexes;
388
389   SUIT_DataOwnerPtrList aList;
390   selected( aList );
391
392   for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
393   {
394     const LightApp_DataSubOwner* subOwner =
395       dynamic_cast<const LightApp_DataSubOwner*>( (*itr).operator->() );
396     if ( subOwner )
397     {
398 //#ifndef WNT
399       if ( !theMap.IsBound( TCollection_AsciiString(subOwner->entry().toLatin1().data()) ) )
400 //#else
401 //      if ( !theMap.IsBound( subOwner->entry().toLatin1().data() ) )
402 //#endif
403       {
404         anIndexes.Clear();
405         //Bug 17269: GetIndexes( subOwner->entry(), anIndexes );
406         //Bug 17269: To avoid multiple calling of selected(aList)
407         for ( SUIT_DataOwnerPtrList::const_iterator itr2 = itr; itr2 != aList.end(); ++itr2 )
408         {
409           const LightApp_DataSubOwner* subOwner2 =
410             dynamic_cast<const LightApp_DataSubOwner*>( (*itr2).operator->() );
411           if ( subOwner2 )
412             if ( subOwner2->entry() == subOwner->entry() )
413               anIndexes.Add( subOwner2->index() );
414         }
415         //
416         theMap.Bind( subOwner->entry().toLatin1().data(), anIndexes );
417       }
418     }
419   }
420 }
421
422 #endif
423
424 void LightApp_SelectionMgr::clearSelectionCache()
425 {
426   myCacheTimes.clear();
427   myCacheSelection.clear();
428 }
429
430 bool LightApp_SelectionMgr::isSelectionCacheEnabled() const
431 {
432   return myCacheState;
433 }
434
435 void LightApp_SelectionMgr::setSelectionCacheEnabled( bool on )
436 {
437   if ( myCacheState == on )
438     return;
439
440   myCacheState = on;
441
442   if ( !myCacheState )
443     clearSelectionCache();
444 }
445
446 #ifndef DISABLE_SALOMEOBJECT
447
448 QList<Handle_SALOME_InteractiveObject> LightApp_SelectionMgr::selectionCache( const QString& type ) const
449 {
450   QList<Handle_SALOME_InteractiveObject> res;
451
452   QStringList types;
453   if ( !type.isEmpty() )
454     types.append( type );
455   else
456     types = selectorTypes();
457
458   QSet<QString> set;
459   for ( QStringList::iterator it = types.begin(); it != types.end(); ++it ) {
460     if ( myCacheSelection.contains( *it ) ) {
461       const SelList& lst = myCacheSelection[*it];
462       for ( SelList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr ) {
463         if ( !(*itr).IsNull() && !set.contains( (*itr)->getEntry() ) ) {
464           res.append( *itr );
465           set.insert( (*itr)->getEntry() );
466         }
467       }
468     }
469   }
470   return res;
471 }
472
473 #else
474
475 QStringList LightApp_SelectionMgr::selectionCache( const QString& type ) const
476 {
477   QStringList res;
478
479   QStringList types;
480   if ( !type.isEmpty() )
481     types.append( type );
482   else
483     types = selectorTypes();
484
485   QSet<QString> set;
486   for ( QStringList::iterator it = types.begin(); it != types.end(); ++it ) {
487     if ( myCacheSelection.contains( *it ) ) {
488       const SelList& lst = myCacheSelection[*it];
489       for ( SelList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr ) {
490         if ( !set.contains( *itr ) ) {
491           res.append( *itr );
492           set.insert( *itr );
493         }
494       }
495     }
496   }
497   return res;
498 }
499
500 #endif
501
502 bool LightApp_SelectionMgr::isActualSelectionCache( const QString& type ) const
503 {
504   bool ok = true;
505
506   QStringList types;
507   if ( !type.isEmpty() )
508     types.append( type );
509   else
510     types = selectorTypes();
511
512   for ( QStringList::iterator it = types.begin(); it != types.end() && ok; ++it )
513     ok = myCacheTimes.contains( *it ) && myCacheTimes[*it].isValid() && myCacheTimes[*it] >= myTimeStamp;
514
515   return ok;
516 }
517
518 QStringList LightApp_SelectionMgr::selectorTypes() const
519 {
520   QStringList types;
521   QList<SUIT_Selector*> selectorList;
522   selectors( selectorList );
523   for ( QList<SUIT_Selector*>::const_iterator it = selectorList.begin(); it != selectorList.end(); ++it ) {
524     if ( (*it)->isEnabled() )
525       types.append( (*it)->type() );
526   }
527   return types;
528 }