Salome HOME
Debug of CMake build procedure
[modules/gui.git] / src / LightApp / LightApp_SelectionMgr.cxx
1 // Copyright (C) 2007-2014  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 "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() ) && !owner->IO().IsNull() ) {
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 /*!
232   Append selected objects.
233 */
234 void LightApp_SelectionMgr::setSelectedObjects( const QStringList& lst, const bool append )
235 {
236   SUIT_DataOwnerPtrList owners;
237   foreach( const QString& aValue, lst ) {
238     if ( !aValue.isNull() )
239       owners.append( new LightApp_DataOwner( aValue ) );
240   }
241
242   setSelected( owners, append );
243 }
244
245 #endif
246
247 /*!
248   Emit current selection changed.
249 */
250 void LightApp_SelectionMgr::selectionChanged( SUIT_Selector* theSel )
251 {
252   SUIT_SelectionMgr::selectionChanged( theSel );
253
254   myTimeStamp = QTime::currentTime();
255
256   emit currentSelectionChanged();
257 }
258
259 #ifndef DISABLE_SALOMEOBJECT
260
261 /*!
262   get map of indexes for the given SALOME_InteractiveObject
263 */
264 void LightApp_SelectionMgr::GetIndexes( const Handle(SALOME_InteractiveObject)& IObject,
265                                         TColStd_IndexedMapOfInteger& theIndex)
266 {
267   theIndex.Clear();
268
269   SUIT_DataOwnerPtrList aList;
270   selected( aList );
271
272   for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
273   {
274     LightApp_DataSubOwner* subOwner = dynamic_cast<LightApp_DataSubOwner*>( (*itr).operator->() );
275     if ( subOwner && subOwner->entry() == QString(IObject->getEntry()) )
276       theIndex.Add( subOwner->index() );
277   }
278 }
279
280 /*!
281   get map of indexes for the given entry of SALOME_InteractiveObject
282 */
283 void LightApp_SelectionMgr::GetIndexes( const QString& theEntry, TColStd_IndexedMapOfInteger& theIndex )
284 {
285   theIndex.Clear();
286
287   SUIT_DataOwnerPtrList aList;
288   selected( aList );
289
290   for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
291   {
292     const LightApp_DataSubOwner* subOwner = dynamic_cast<const LightApp_DataSubOwner*>( (*itr).operator->() );
293     if ( subOwner )
294       if ( subOwner->entry() == theEntry )
295         theIndex.Add( subOwner->index() );
296   }
297
298 }
299
300 /*!
301   Add or remove interactive objects from selection manager.
302 */
303 //bool LightApp_SelectionMgr::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& IObject,
304 void LightApp_SelectionMgr::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& IObject,
305                                               const TColStd_MapOfInteger& theIndexes,
306                                               bool modeShift)
307 {
308   SUIT_DataOwnerPtrList remainsOwners;
309
310   SUIT_DataOwnerPtrList aList;
311   selected( aList );
312
313   QString ioEntry (IObject->getEntry());
314
315   if ( !modeShift ) {
316     for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
317     {
318       const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr).operator->() );
319       if ( owner )
320       {
321         if ( owner->entry() != ioEntry )
322         {
323           const LightApp_DataSubOwner* subOwner = dynamic_cast<const LightApp_DataSubOwner*>( owner );
324           if ( subOwner )
325             remainsOwners.append( new LightApp_DataSubOwner( subOwner->entry(), subOwner->index() ) );
326           else
327             remainsOwners.append( new LightApp_DataOwner( owner->entry() ) );
328         }
329       }
330     }
331   }
332   else
333     remainsOwners = aList;
334
335   TColStd_MapIteratorOfMapOfInteger It;
336   It.Initialize(theIndexes);
337   for(;It.More();It.Next())
338     remainsOwners.append( new LightApp_DataSubOwner( ioEntry, It.Key() ) );
339
340   bool append = false;
341   setSelected( remainsOwners, append );
342
343   emit currentSelectionChanged();
344
345   // Bug 17269: To avoid calling of selected(aList)
346   //TColStd_IndexedMapOfInteger anIndexes;
347   //GetIndexes( IObject, anIndexes );
348   //return !anIndexes.IsEmpty();
349 }
350
351 /*!
352   select 'subobjects' with given indexes
353 */
354 void LightApp_SelectionMgr::selectObjects( const Handle(SALOME_InteractiveObject)& IObject,
355                                             TColStd_IndexedMapOfInteger theIndex, bool append )
356 {
357   SUIT_DataOwnerPtrList aList;
358
359   if ( theIndex.IsEmpty() )
360     aList.append( new LightApp_DataOwner( QString(IObject->getEntry()) ) );
361   else
362     {
363       int i;
364       for ( i = 1; i <= theIndex.Extent(); i++ )
365         aList.append( new LightApp_DataSubOwner( QString(IObject->getEntry()), theIndex( i ) ) );
366     }
367
368   setSelected( aList, append );
369 }
370
371 /*!
372   select 'subobjects' with given indexes
373 */
374 void LightApp_SelectionMgr::selectObjects( MapIOOfMapOfInteger theMapIO, bool append )
375 {
376   SUIT_DataOwnerPtrList aList;
377
378   MapIOOfMapOfInteger::Iterator it(theMapIO);
379   for ( ; it.More(); it.Next() )
380     {
381       if ( it.Value().IsEmpty() )
382         aList.append( new LightApp_DataOwner( QString(it.Key()->getEntry()) ) );
383       else
384         {
385           int i;
386           for ( i = 1; i <= it.Value().Extent(); i++ )
387             aList.append( new LightApp_DataSubOwner( QString(it.Key()->getEntry()), it.Value()( i ) ) );
388         }
389     }
390
391   setSelected( aList, append );
392 }
393
394 /*!
395   get map of selected subowners : object's entry <-> map of indexes
396 */
397 void LightApp_SelectionMgr::selectedSubOwners( MapEntryOfMapOfInteger& theMap )
398 {
399   theMap.Clear();
400
401   TColStd_IndexedMapOfInteger anIndexes;
402
403   SUIT_DataOwnerPtrList aList;
404   selected( aList );
405
406   for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
407   {
408     const LightApp_DataSubOwner* subOwner =
409       dynamic_cast<const LightApp_DataSubOwner*>( (*itr).operator->() );
410     if ( subOwner )
411     {
412 //#ifndef WIN32
413       if ( !theMap.IsBound( TCollection_AsciiString(subOwner->entry().toLatin1().data()) ) )
414 //#else
415 //      if ( !theMap.IsBound( subOwner->entry().toLatin1().data() ) )
416 //#endif
417       {
418         anIndexes.Clear();
419         //Bug 17269: GetIndexes( subOwner->entry(), anIndexes );
420         //Bug 17269: To avoid multiple calling of selected(aList)
421         for ( SUIT_DataOwnerPtrList::const_iterator itr2 = itr; itr2 != aList.end(); ++itr2 )
422         {
423           const LightApp_DataSubOwner* subOwner2 =
424             dynamic_cast<const LightApp_DataSubOwner*>( (*itr2).operator->() );
425           if ( subOwner2 )
426             if ( subOwner2->entry() == subOwner->entry() )
427               anIndexes.Add( subOwner2->index() );
428         }
429         //
430         theMap.Bind( subOwner->entry().toLatin1().data(), anIndexes );
431       }
432     }
433   }
434 }
435
436 #endif
437
438 void LightApp_SelectionMgr::clearSelectionCache()
439 {
440   myCacheTimes.clear();
441   myCacheSelection.clear();
442 }
443
444 bool LightApp_SelectionMgr::isSelectionCacheEnabled() const
445 {
446   return myCacheState;
447 }
448
449 void LightApp_SelectionMgr::setSelectionCacheEnabled( bool on )
450 {
451   if ( myCacheState == on )
452     return;
453
454   myCacheState = on;
455
456   if ( !myCacheState )
457     clearSelectionCache();
458 }
459
460 #ifndef DISABLE_SALOMEOBJECT
461
462 QList<Handle_SALOME_InteractiveObject> LightApp_SelectionMgr::selectionCache( const QString& type ) const
463 {
464   QList<Handle_SALOME_InteractiveObject> res;
465
466   QStringList types;
467   if ( !type.isEmpty() )
468     types.append( type );
469   else
470     types = selectorTypes();
471
472   QSet<QString> set;
473   for ( QStringList::iterator it = types.begin(); it != types.end(); ++it ) {
474     if ( myCacheSelection.contains( *it ) ) {
475       const SelList& lst = myCacheSelection[*it];
476       for ( SelList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr ) {
477         if ( !(*itr).IsNull() && !set.contains( (*itr)->getEntry() ) ) {
478           res.append( *itr );
479           set.insert( (*itr)->getEntry() );
480         }
481       }
482     }
483   }
484   return res;
485 }
486
487 #else
488
489 QStringList LightApp_SelectionMgr::selectionCache( const QString& type ) const
490 {
491   QStringList res;
492
493   QStringList types;
494   if ( !type.isEmpty() )
495     types.append( type );
496   else
497     types = selectorTypes();
498
499   QSet<QString> set;
500   for ( QStringList::iterator it = types.begin(); it != types.end(); ++it ) {
501     if ( myCacheSelection.contains( *it ) ) {
502       const SelList& lst = myCacheSelection[*it];
503       for ( SelList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr ) {
504         if ( !set.contains( *itr ) ) {
505           res.append( *itr );
506           set.insert( *itr );
507         }
508       }
509     }
510   }
511   return res;
512 }
513
514 #endif
515
516 bool LightApp_SelectionMgr::isActualSelectionCache( const QString& type ) const
517 {
518   bool ok = true;
519
520   QStringList types;
521   if ( !type.isEmpty() )
522     types.append( type );
523   else
524     types = selectorTypes();
525
526   for ( QStringList::iterator it = types.begin(); it != types.end() && ok; ++it )
527     ok = myCacheTimes.contains( *it ) && myCacheTimes[*it].isValid() && myCacheTimes[*it] >= myTimeStamp;
528
529   return ok;
530 }
531
532 QStringList LightApp_SelectionMgr::selectorTypes() const
533 {
534   QStringList types;
535   QList<SUIT_Selector*> selectorList;
536   selectors( selectorList );
537   for ( QList<SUIT_Selector*>::const_iterator it = selectorList.begin(); it != selectorList.end(); ++it ) {
538     if ( (*it)->isEnabled() )
539       types.append( (*it)->type() );
540   }
541   return types;
542 }