Salome HOME
Porting to Mandrake 10.1 and new products:
[modules/kernel.git] / src / SALOMEGUI / SALOME_Selection.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOME_Selection.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SALOME
27 //  $Header$
28
29 /*!
30   \class SALOME_Selection SALOME_Selection.h
31   \brief Selection Mechanism of Interactive Object.
32 */
33
34 #include "SALOME_Selection.h"
35 #include "SALOME_Filter.hxx"
36 #include "SALOME_InteractiveObject.hxx"
37 #include "SALOME_ListIteratorOfListIO.hxx"
38 #include "SALOME_ListIteratorOfListOfFilter.hxx"
39
40 #include "QAD_Desktop.h"
41 #include "utilities.h"
42
43 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
44 #include <TColStd_IndexedMapOfInteger.hxx>
45
46 #ifdef _DEBUG_
47 static int MYDEBUG = 0;
48 #else
49 static int MYDEBUG = 0;
50 #endif
51
52 using namespace std;
53
54 static QList<SALOME_Selection>&  SALOME_Sel_GetSelections()
55 {
56   static QList<SALOME_Selection> Selections;
57   return Selections;
58 }
59
60 //=======================================================================
61 //                       SELECTIONS MANAGEMENT
62 //=======================================================================
63
64 /*!
65   Constructor
66 */
67 SALOME_Selection::SALOME_Selection(const QString& aName) :
68   myName(aName)
69 {
70   myFilters.Clear();
71   myIObjects.Clear();
72   mySelectionMode = ActorSelection; /*4*/
73   mySelActiveCompOnly = false;
74   
75   QAD_Desktop* aDesktop = QAD_Application::getDesktop();
76   if (aDesktop) {
77     QAD_Application *anActiveApplication = aDesktop->getActiveApp();
78     if (anActiveApplication) QAD_ASSERT(connect(this, SIGNAL(currentSelectionChanged()),anActiveApplication, SLOT(updateActions())));
79   }
80 }
81
82 /*!
83   Destructor
84 */
85 SALOME_Selection::~SALOME_Selection()
86 {
87 }
88
89 /*!
90   Create a Selection with name \a aName
91   \return TRUE if the Selection is created. Returns FALSE otherwise. 
92 */
93 bool SALOME_Selection::CreateSelection(const QString& aName)
94
95   SALOME_Selection* S = NULL;
96   if ( SALOME_Selection::FindSelection( aName ) )
97     S = SALOME_Selection::Selection( aName );
98   else {
99     S = new SALOME_Selection(aName);
100     SALOME_Sel_GetSelections().prepend(S);
101   }
102   return true;
103 }
104
105
106 /*!
107   Sets the current Selection with \a aName
108 */
109 SALOME_Selection* SALOME_Selection::Selection(const QString& aName) 
110 {
111   SALOME_Selection* Sel = NULL;
112   if(SALOME_Sel_GetSelections().isEmpty()) return Sel;
113
114   for( Sel=SALOME_Sel_GetSelections().first(); Sel!=0; Sel=SALOME_Sel_GetSelections().next() ){
115     if( Sel->myName.compare(aName) == 0 ) 
116       return Sel;
117   }
118   
119   return Sel;
120 }
121
122 /*!
123   Finds Selection with \a aName
124   \return TRUE if the Selection is found. Returns FALSE otherwise. 
125 */
126 bool SALOME_Selection::FindSelection(const QString& aName) 
127 {
128   SALOME_Selection* Sel;
129   for( Sel=SALOME_Sel_GetSelections().first(); Sel!=0; Sel=SALOME_Sel_GetSelections().next() ){
130     if( Sel->myName.compare(aName) == 0 )
131       return true;
132   }
133
134   return false;
135 }
136
137 /*!
138   Removes Selection with \a aName
139   \return TRUE if the Selection is removed. Returns FALSE otherwise. 
140 */
141 bool SALOME_Selection::RemoveSelection(const QString& aName) 
142 {
143   SALOME_Selection* Sel;
144   for( Sel=SALOME_Sel_GetSelections().first(); Sel!=0; Sel=SALOME_Sel_GetSelections().next() ){
145     if( Sel->myName.compare(aName) == 0 )
146        return SALOME_Sel_GetSelections().remove(Sel);
147   }
148   return false;
149 }
150
151
152
153 //=======================================================================
154 //                                FILTERS MANAGEMENT
155 //=======================================================================
156
157 /*!
158   Adds Filter
159 */
160 void SALOME_Selection::AddFilter(const Handle(SALOME_Filter)& aFilter,
161                                  bool updateSelection) 
162 {
163   if ( !FindFilter(aFilter) ) {
164     myFilters.Append( aFilter );
165
166     SALOME_ListIO removedIObjects;
167
168     if ( updateSelection ) {
169       SALOME_ListIteratorOfListIO It(myIObjects);
170       for(;It.More();It.Next()){
171         Handle(SALOME_InteractiveObject) Object = It.Value();
172         if( !IsOk(Object) ) {
173           removedIObjects.Append( Object );
174           //      RemoveIObject( Object );
175         }
176       }
177       
178       SALOME_ListIteratorOfListIO It1(removedIObjects);
179       for(;It1.More();It1.Next()){
180         Handle(SALOME_InteractiveObject) Object = It1.Value();
181         RemoveIObject( Object );
182       }
183     }
184   }
185 }
186
187 /*!
188   Removes Filter
189 */
190 bool SALOME_Selection::RemoveFilter(const Handle(SALOME_Filter)& aFilter) 
191 {
192   SALOME_ListIteratorOfListOfFilter It(myFilters);
193   for(;It.More();It.Next()){
194     if (aFilter==It.Value()){ 
195       myFilters.Remove(It);
196       return true;
197     }
198   }
199   return false;
200 }
201
202 //! Clears All Filters
203 void SALOME_Selection::ClearFilters()
204 {
205   myFilters.Clear();
206 }
207
208 //! Finds aFilter 
209 bool SALOME_Selection::FindFilter(const Handle(SALOME_Filter)& aFilter) 
210 {
211   SALOME_ListIteratorOfListOfFilter It(myFilters);
212   for(;It.More();It.Next())
213     if (aFilter==It.Value()) 
214       return true;
215   return false;
216 }
217
218 //! Returns the list of stored Filters
219 const SALOME_ListOfFilter& SALOME_Selection::StoredFilters()
220 {
221   return myFilters;
222 }
223
224
225
226 //=======================================================================
227 //                     INTERACTIVE OBJECTS MANAGEMENT
228 //=======================================================================
229
230 void SALOME_Selection::Clear() 
231 {
232   myIObjects.Clear();
233 }
234
235 //! Clears all Interactive Objects
236 void SALOME_Selection::ClearIObjects() 
237 {
238   myIObjects.Clear();
239
240   QAD_Desktop*   myDesktop = (QAD_Desktop*) QAD_Application::getDesktop();
241   QAD_Study* myActiveStudy = myDesktop->getActiveStudy();
242   myActiveStudy->unHighlightAll();
243
244   myMapIOSubIndex.Clear();
245
246   emit currentSelectionChanged();
247 }
248
249 //! Add an InteractiveObject
250 int SALOME_Selection::AddIObject(const Handle(SALOME_InteractiveObject)& anObject, bool update) 
251 {
252   QAD_Desktop*   myDesktop = (QAD_Desktop*) QAD_Application::getDesktop();
253   QAD_Study* myActiveStudy = myDesktop->getActiveStudy();
254
255   if ( !IsOk(anObject) ) {
256     if(MYDEBUG) INFOS ( "The Object not authorized by Filters" )
257     myActiveStudy->highlight(anObject,false, update);
258     return -1;
259   }
260
261   bool Found = false;
262   SALOME_ListIteratorOfListIO It(myIObjects);
263   for(;It.More();It.Next()) {
264     if (anObject->isSame(It.Value())) {
265       Found = true;
266       break;
267     }
268   }
269
270   // Il n'est pas dedans, on le rajoute....
271   if(Found==false) {
272     myIObjects.Append( anObject );
273     myActiveStudy->highlight(anObject, true, update);
274     emit currentSelectionChanged();
275     return 1;
276   }
277   return 0;
278 }
279
280 //! Removes an InteractiveObject
281 int SALOME_Selection::RemoveIObject(const Handle(SALOME_InteractiveObject)& anObject, bool update) 
282 {
283   SALOME_ListIteratorOfListIO It(myIObjects);
284   for(;It.More();It.Next()) {
285     if (anObject->isSame(It.Value())) {
286       QAD_Desktop*   myDesktop = (QAD_Desktop*) QAD_Application::getDesktop();
287       QAD_Study* myActiveStudy = myDesktop->getActiveStudy();
288       myActiveStudy->highlight(anObject, false, update);
289
290       if ( myMapIOSubIndex.IsBound( anObject ) ) {
291         myMapIOSubIndex.UnBind( anObject );
292       }
293       
294       myIObjects.Remove(It);
295
296       emit currentSelectionChanged();
297       return 1; 
298     }
299   }
300   return 0;
301 }
302
303 //! Returns the list of InteractiveObjects
304 const SALOME_ListIO& SALOME_Selection::StoredIObjects()
305 {
306   return myIObjects;
307 }
308
309 //! Returns the number of InteractiveObjects in the selection. 
310 int SALOME_Selection::IObjectCount()
311 {
312   return myIObjects.Extent();
313 }
314
315 //!  Returns the first InteractiveObject in the selection.
316 Handle(SALOME_InteractiveObject) SALOME_Selection::firstIObject()
317 {
318   return myIObjects.Extent() > 0 ? myIObjects.First() : Handle(SALOME_InteractiveObject)();
319 }
320
321 //! Returns the last InteractiveObject in the selection.
322 Handle(SALOME_InteractiveObject) SALOME_Selection::lastIObject()
323 {
324   return myIObjects.Extent() > 0 ? myIObjects.Last() : Handle(SALOME_InteractiveObject)();
325 }
326
327 /*!
328   Returns TRUE if the InteractiveObject is authorized by Filters. Returns FALSE otherwise.
329 */
330 bool SALOME_Selection::IsOk(const Handle(SALOME_InteractiveObject)& anObj)
331 {
332   SALOME_ListIteratorOfListOfFilter It(myFilters);
333   for(;It.More();It.Next()){
334     Handle(SALOME_Filter) theFilter = It.Value();
335     if ( !theFilter->IsOk(anObj) ) 
336       return false;
337   }
338   return true;
339 }
340
341 void SALOME_Selection::SetSelectionMode(Selection_Mode mode, bool activeCompOnly)
342 {
343   mySelectionMode = mode;
344   mySelActiveCompOnly = activeCompOnly;
345 }
346
347 Selection_Mode SALOME_Selection::SelectionMode()
348 {
349   return mySelectionMode;
350 }
351
352 bool SALOME_Selection::IsSelectActiveCompOnly() const
353 {
354   return mySelActiveCompOnly;
355 }
356
357 bool SALOME_Selection::HasIndex( const Handle(SALOME_InteractiveObject)& IObject )
358 {
359   return myMapIOSubIndex.IsBound(IObject);
360 }
361
362 void SALOME_Selection::GetIndex( const Handle(SALOME_InteractiveObject)& IObject, TColStd_IndexedMapOfInteger& theIndex )
363 {
364   if ( myMapIOSubIndex.IsBound(IObject) ) {
365     theIndex = myMapIOSubIndex.Find(IObject);
366   }
367   else {
368     theIndex.Clear();
369   }
370 }
371
372
373
374 bool SALOME_Selection::IsIndexSelected(const Handle(SALOME_InteractiveObject)& IObject, int index)
375 {
376   if ( !myMapIOSubIndex.IsBound( IObject ) ) {
377     return false;
378   }
379   TColStd_IndexedMapOfInteger& MapIndex = myMapIOSubIndex.ChangeFind( IObject );
380   return MapIndex.Contains( index );
381 }
382
383 static bool removeIndex( TColStd_IndexedMapOfInteger& MapIndex,
384                         const int                     Index)
385 {
386   int i = MapIndex.FindIndex( Index ); // i==0 if Index is not in the MapIndex
387   if ( i ) {
388     // only the last key can be removed
389     int indexLast = MapIndex.FindKey( MapIndex.Extent() );
390     if ( indexLast == Index )
391       MapIndex.RemoveLast();
392     else {
393       TColStd_IndexedMapOfInteger aNewMap;
394       aNewMap.ReSize( MapIndex.Extent() - 1 );
395       for ( int j = 1; j <= MapIndex.Extent(); j++ ) {
396         int ind = MapIndex( j );
397         if ( ind != Index )
398           aNewMap.Add( ind );
399       }
400       MapIndex = aNewMap;
401     }
402   }
403   return i;
404 }
405
406
407 bool SALOME_Selection::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& IObject, 
408                                          int index, 
409                                          bool modeShift,
410                                          bool update)
411 {
412   if(MYDEBUG) INFOS( " SALOME_Selection::AddOrRemoveIndex " << index << " - " << modeShift );
413   QAD_Desktop*   myDesktop = (QAD_Desktop*) QAD_Application::getDesktop();
414   QAD_Study* myActiveStudy = myDesktop->getActiveStudy();
415
416   if ( !myMapIOSubIndex.IsBound( IObject ) ) {
417     TColStd_IndexedMapOfInteger Empty;
418     myMapIOSubIndex.Bind( IObject, Empty );
419   }
420   TColStd_IndexedMapOfInteger& MapIndex = myMapIOSubIndex.ChangeFind( IObject );
421
422   bool anIsConatains = MapIndex.Contains( index );
423
424   if (anIsConatains)
425     removeIndex( MapIndex, index );
426   
427   if (!modeShift)
428     MapIndex.Clear();
429   
430   if(!anIsConatains)
431     MapIndex.Add( index );
432
433   if ( MapIndex.IsEmpty() ) {
434     myMapIOSubIndex.UnBind( IObject );
435     RemoveIObject( IObject, update );
436   }
437
438   myActiveStudy->highlight( IObject, true, update );    
439
440   emit currentSelectionChanged();
441   return false;
442 }
443
444 bool SALOME_Selection::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& IObject, 
445                                          const TColStd_MapOfInteger& theIndices, 
446                                          bool modeShift,
447                                          bool update)
448 {
449   QAD_Desktop*   myDesktop = (QAD_Desktop*) QAD_Application::getDesktop();
450   QAD_Study* myActiveStudy = myDesktop->getActiveStudy();
451   
452   if ( !myMapIOSubIndex.IsBound( IObject ) ) {
453     TColStd_IndexedMapOfInteger Empty;
454     myMapIOSubIndex.Bind( IObject, Empty );
455   }
456   TColStd_IndexedMapOfInteger& MapIndex = myMapIOSubIndex.ChangeFind( IObject );
457   TColStd_MapIteratorOfMapOfInteger It;
458   It.Initialize(theIndices);
459   
460   if (!modeShift)
461     MapIndex.Clear();
462   
463   for(;It.More();It.Next())
464     MapIndex.Add(It.Key());
465   
466   if ( MapIndex.IsEmpty() ) {
467     myMapIOSubIndex.UnBind( IObject );
468     RemoveIObject( IObject, update );
469   }
470
471   myActiveStudy->highlight( IObject, true, update );    
472
473   emit currentSelectionChanged();
474   
475   return !MapIndex.IsEmpty();
476 }
477
478 bool SALOME_Selection::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& IObject, 
479                                          const TContainerOfId& theIndices, 
480                                          bool modeShift,
481                                          bool update)
482 {
483   QAD_Desktop*   myDesktop = (QAD_Desktop*) QAD_Application::getDesktop();
484   QAD_Study* myActiveStudy = myDesktop->getActiveStudy();
485   
486   if ( !myMapIOSubIndex.IsBound( IObject ) ) {
487     TColStd_IndexedMapOfInteger Empty;
488     myMapIOSubIndex.Bind( IObject, Empty );
489   }
490   TColStd_IndexedMapOfInteger& MapIndex = myMapIOSubIndex.ChangeFind( IObject );
491       
492   if (!modeShift)
493     MapIndex.Clear();
494   
495   TContainerOfId::const_iterator anIter = theIndices.begin();
496   TContainerOfId::const_iterator anIterEnd = theIndices.end();
497   for(; anIter != anIterEnd; anIter++)
498     MapIndex.Add(*anIter); 
499
500   if ( MapIndex.IsEmpty() ) {
501     myMapIOSubIndex.UnBind( IObject );
502     RemoveIObject( IObject, update );
503   }
504
505   myActiveStudy->highlight( IObject, true, update );    
506
507   emit currentSelectionChanged();
508   
509   return !MapIndex.IsEmpty();
510 }
511
512 void SALOME_Selection::RemoveIndex( const Handle(SALOME_InteractiveObject)& IObject, int index )
513 {
514   if ( myMapIOSubIndex.IsBound( IObject ) ) {
515     TColStd_IndexedMapOfInteger& MapIndex = myMapIOSubIndex.ChangeFind( IObject );
516     removeIndex( MapIndex, index );
517   }
518 }
519
520 void SALOME_Selection::ClearIndex()
521 {
522   myMapIOSubIndex.Clear();  
523 }
524
525
526 //================================================================
527 // Function : GEOMBase_Helper
528 // Purpose  : Block signal currentSelectionChanged. Use this method to
529 //            deactivate signal before big modification of selection.
530 //            After this modification this signal must be activated and
531 //            method SelectionChanged must be called to notify other oblects
532 //            ( dialogs for example )
533 //================================================================
534 void SALOME_Selection::BlockSignals( const bool theState )
535 {
536   blockSignals( theState );
537 }
538
539 //================================================================
540 // Function : SelectionChanged
541 // Purpose  : Enit signal currentSelectionChanged()
542 //================================================================
543 void SALOME_Selection::SelectionChanged()
544 {
545   emit currentSelectionChanged();
546 }