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