Salome HOME
Implement level() method for the SUIT_DataObject class
[modules/gui.git] / src / SUIT / SUIT_DataObject.cxx
1 #include "SUIT_DataObject.h"
2
3 #include <qobject.h>
4
5 #include "SUIT_DataObjectKey.h"
6
7 #include <iostream> // for cout in dump()
8
9 /*!
10     Constructor
11 */
12
13 SUIT_DataObject::SUIT_DataObject( SUIT_DataObject* p )
14 : myParent( 0 ),
15   mySignal( 0 ),
16   myOpen( false ),
17   myCheck( false )
18 {
19   myChildren.setAutoDelete( true );
20
21   setParent( p );
22 }
23
24 /*!
25     Destructor
26 */
27
28 SUIT_DataObject::~SUIT_DataObject()
29 {
30   if ( mySignal )
31   {
32     mySignal->emitSignal();
33     mySignal->setOwner( 0 );
34   }
35
36   delete mySignal;
37
38   SUIT_DataObject* p = myParent;
39
40   myParent = 0;
41
42   if ( p )
43     p->removeChild( this );
44
45   for ( QPtrListIterator<SUIT_DataObject> it( myChildren ); it.current(); ++it )
46     it.current()->myParent = 0;
47 }
48
49 /*!
50     Returns the root object.
51 */
52
53 SUIT_DataObject* SUIT_DataObject::root() const
54 {
55   return parent() ? parent()->root() : (SUIT_DataObject*)this;
56 }
57
58 /*!
59     Returns the first child object.
60 */
61
62 SUIT_DataObject* SUIT_DataObject::firstChild() const
63 {
64   SUIT_DataObject* child = 0;
65   if ( !myChildren.isEmpty() )
66     child = myChildren.getFirst();
67   return child;
68 }
69
70 /*!
71     Returns the last child object.
72 */
73
74 SUIT_DataObject* SUIT_DataObject::lastChild() const
75 {
76   SUIT_DataObject* child = 0;
77   if ( !myChildren.isEmpty() )
78     child = myChildren.getLast();
79   return child;
80 }
81
82 /*!
83     Returns the number of the child objects.
84 */
85
86 int SUIT_DataObject::childCount() const
87 {
88   return myChildren.count();
89 }
90
91 /*!
92     Returns the index of the specified object in the child list or -1.
93 */
94
95 int SUIT_DataObject::childPos( const SUIT_DataObject* obj ) const
96 {
97   int res = -1;
98
99   int i = 0;
100   for ( DataObjectListIterator it( myChildren ); it.current() && res == -1; ++it, i++ )
101   {
102     if ( it.current() == obj )
103       res = i;
104   }
105
106   return res;
107 }
108
109 /*!
110     Returns the child object with specified index.
111 */
112
113 SUIT_DataObject* SUIT_DataObject::childObject( const int idx ) const
114 {
115   SUIT_DataObject* child = 0;
116
117   if ( idx>= 0 && idx < (int)myChildren.count() )
118   {
119     SUIT_DataObject* that = (SUIT_DataObject*)this;
120     child = that->myChildren.at( idx );
121   }
122
123   return child;
124 }
125
126 /*!
127     Returns the level of the object in the data tree.
128     0 means that object is top-level.
129 */
130
131 int SUIT_DataObject::level() const
132 {
133   int lev = 0;
134   SUIT_DataObject* p = parent();
135   while ( p ) {
136     p = p->parent();
137     lev++;
138   }
139   return lev;
140 }
141
142 /*!
143     Returns the next data object in the child list of the parent.
144 */
145
146 SUIT_DataObject* SUIT_DataObject::nextBrother() const
147 {
148   return myParent ? myParent->childObject( myParent->childPos( this ) + 1 ) : 0;
149 }
150
151 /*!
152     Returns the previous data object in the child list of the parent.
153 */
154
155 SUIT_DataObject* SUIT_DataObject::prevBrother() const
156 {
157   return myParent ? myParent->childObject( myParent->childPos( this ) - 1 ) : 0;
158 }
159
160 /*!
161     Returns 'true' if the object will delete children during destroying
162 */
163
164 bool SUIT_DataObject::autoDeleteChildren() const
165 {
166   return myChildren.autoDelete();
167 }
168
169 /*!
170     Specify should the object delete children during destroying
171 */
172
173 void SUIT_DataObject::setAutoDeleteChildren( const bool on )
174 {
175   myChildren.setAutoDelete( on );
176 }
177
178 /*!
179     Returns the list of the child objects. if 'rec' is 'true' then function get all sub children.
180 */
181
182 void SUIT_DataObject::children( DataObjectList& lst, const bool rec ) const
183 {
184   for ( DataObjectListIterator it( myChildren ); it.current(); ++it )
185   {
186     lst.append( it.current() );
187     if ( rec )
188       it.current()->children( lst, rec );
189   }
190 }
191
192 /*!
193     Returns the list of the child objects. if 'rec' is 'true' then function get all sub children.
194 */
195
196 DataObjectList SUIT_DataObject::children( const bool rec )
197 {
198   DataObjectList lst;
199   children( lst, rec );
200   return lst;
201 }
202
203 /*!
204     Append new child object to the end of the children list
205 */
206
207 void SUIT_DataObject::appendChild( SUIT_DataObject* theObj ) 
208 {
209   insertChild( theObj, myChildren.count() );
210 }
211
212 /*!
213     Insert new child object to the children list at specified position
214 */
215
216 void SUIT_DataObject::insertChild( SUIT_DataObject* theObj, int thePosition )
217 {
218   if ( !theObj || myChildren.find( theObj ) != -1 )
219     return;
220
221   int pos = thePosition < 0 ? myChildren.count() : thePosition;
222   myChildren.insert( QMIN( pos, (int)myChildren.count() ), theObj );
223   theObj->setParent( this );
224 }
225
226 /*!
227     Removes the specified child object reference.
228 */
229
230 void SUIT_DataObject::removeChild( SUIT_DataObject* theObj )
231 {
232   if ( !theObj )
233     return;
234
235   bool ad = myChildren.autoDelete();
236   myChildren.setAutoDelete( false );
237
238   if ( myChildren.remove( theObj ) )
239     theObj->setParent( 0 );
240
241   myChildren.setAutoDelete( ad );
242 }
243
244 /*!
245     Replaces the specified child object by another object.
246 */
247
248 bool SUIT_DataObject::replaceChild( SUIT_DataObject* src, SUIT_DataObject* trg, const bool del )
249 {
250   if ( !src || !trg )
251     return false;
252
253   int idx = childPos( trg );
254   removeChild( trg );
255
256   int pos = childPos( src );
257   if ( pos < 0 )
258   {
259     if ( idx >= 0 )
260       insertChild( trg, idx );
261     return false;
262   }
263
264   insertChild( trg, pos );
265   removeChild( src );
266
267   if ( del )
268     src->deleteLater();
269
270   return true;
271 }
272
273 /*!
274     Transfer the all children from specified object 'obj' to self.
275 */
276
277 void SUIT_DataObject::reparentChildren( const SUIT_DataObject* obj )
278 {
279   DataObjectList lst;
280   obj->children( lst );
281   for ( DataObjectListIterator it( lst ); it.current(); ++it )
282     it.current()->setParent( this );
283 }
284
285 /*!
286     Set the parent object. Remove itself from current parent children
287     and append itself to the new parent children list.
288 */
289
290 void SUIT_DataObject::setParent( SUIT_DataObject* theParent )
291 {
292   if ( theParent == parent() )
293     return;
294
295   if ( parent() )
296     parent()->removeChild( this );
297
298   myParent = theParent;
299
300   if ( parent() )
301     parent()->appendChild( this );
302 }
303
304 /*!
305     Returns the parent object.
306 */
307
308 SUIT_DataObject* SUIT_DataObject::parent() const
309 {
310   return myParent;
311 }
312
313
314 /*!
315     Connect to signal destroyed( SUIT_DataObject* ).
316 */
317
318 bool SUIT_DataObject::connect( QObject* reciever, const char* slot )
319 {
320   if ( !reciever || !slot )
321     return false;
322
323   if ( !mySignal )
324     mySignal = new Signal( this );
325
326   QObject::disconnect( mySignal, SIGNAL( destroyed( SUIT_DataObject* ) ), reciever, slot );
327   return QObject::connect( mySignal, SIGNAL( destroyed( SUIT_DataObject* ) ), reciever, slot );
328 }
329
330 /*!
331     Disconnect from signal destroyed( SUIT_DataObject* ).
332 */
333
334 bool SUIT_DataObject::disconnect( QObject* reciever, const char* slot )
335 {
336   if ( !reciever || !slot )
337     return false;
338
339   if ( !mySignal )
340     return true;
341
342   return QObject::disconnect( mySignal, SIGNAL( destroyed( SUIT_DataObject* ) ), reciever, slot );
343 }
344
345 /*!
346     Returns object name
347 */
348
349 void SUIT_DataObject::deleteLater()
350 {
351   if ( !mySignal )
352     mySignal = new Signal( this );
353   
354   mySignal->emitSignal();
355   mySignal->deleteLater();
356 }
357
358 /*!
359     Returns object name
360 */
361
362 QString SUIT_DataObject::name() const
363 {
364   return QString::null;
365 }
366
367 /*!
368     Returns object icon
369 */
370
371 QPixmap SUIT_DataObject::icon() const
372 {
373   return QPixmap();
374 }
375
376 /*!
377     Returns object text
378 */
379
380 QString SUIT_DataObject::text( const int ) const
381 {
382   return QString::null;
383 }
384
385 /*!
386     Returns object color
387 */
388
389 QColor SUIT_DataObject::color( const ColorRole ) const
390 {
391   return QColor();
392 }
393
394 /*!
395     Returns object tool tip
396 */
397
398 QString SUIT_DataObject::toolTip() const
399 {
400   return QString::null;
401 }
402
403 /*!
404     Returns 'true' if it is possible to drag this object
405 */
406
407 bool SUIT_DataObject::isDragable() const
408 {
409   return false;
410 }
411
412 /*!
413     Returns 'true' if it is possible to drop an object "obj" to this object.
414 */
415
416 bool SUIT_DataObject::isDropAccepted( SUIT_DataObject* )
417 {
418   return false;
419 }
420
421 /*!
422     Returns type of check possibility.
423 */
424
425 SUIT_DataObject::CheckType SUIT_DataObject::checkType() const
426 {
427   return None;
428 }
429
430 /*!
431     Returns the checked state of the object.
432 */
433
434 bool SUIT_DataObject::isOn() const
435 {
436   return myCheck;
437 }
438
439 /*!
440     Sets the checked state of the object.
441 */
442
443 void SUIT_DataObject::setOn( const bool on )
444 {
445   myCheck = on;
446 }
447
448 bool SUIT_DataObject::isOpen() const
449 {
450   return myOpen;
451 }
452
453 void SUIT_DataObject::setOpen( const bool on )
454 {
455   myOpen = on;
456 }
457
458 /*!
459     Returns object personal indentification key.
460 */
461
462 SUIT_DataObjectKey* SUIT_DataObject::key() const
463 {
464   return 0;
465 }
466
467 /*!
468    Dump this data object and its children to cout
469 */
470 void SUIT_DataObject::dump( const int indent ) const
471 {
472   QString strIndent = QString().fill( ' ', indent ); // indentation string 
473   std::cout << strIndent << name() << std::endl;     // dump to cout
474   for ( DataObjectListIterator it( myChildren ); it.current(); ++it ) // iterate all children
475     it.current()->dump( indent + 2 );  // dump every child with indent + 2 spaces
476 }
477
478 /*!
479   Class: SUIT_DataObject::Signal [Internal]
480 */
481
482 SUIT_DataObject::Signal::Signal( SUIT_DataObject* o )
483 : QObject(),
484 myOwner( o )
485 {
486 }
487
488 SUIT_DataObject::Signal::~Signal()
489 {
490   SUIT_DataObject* o = myOwner;
491   myOwner = 0;
492   if ( o )
493   {
494     o->mySignal = 0;
495     delete o;
496   }
497 }
498
499 void SUIT_DataObject::Signal::setOwner( SUIT_DataObject* o )
500 {
501   myOwner = o;
502 }
503
504 void SUIT_DataObject::Signal::emitSignal()
505 {
506   if ( myOwner )
507     emit destroyed( myOwner );
508 }