]> Shamusworld >> Repos - architektonas/blob - src/base/entitycontainer.cpp
7babc889d54de73a4465a732d57777d8745b45bf
[architektonas] / src / base / entitycontainer.cpp
1 // entitycontainer.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  05/28/2010  Added this text. :-)
15 //
16
17 #include "entitycontainer.h"
18
19 #include "debug.h"
20 #include "dimension.h"
21 #include "mathextra.h"
22 #include "layer.h"
23 #include "line.h"
24 #include "polyline.h"
25 #include "text.h"
26 #include "insert.h"
27 #include "spline.h"
28 #include "information.h"
29 #include "graphicview.h"
30 #include "paintinterface.h"
31
32 bool EntityContainer::autoUpdateBorders = true;
33
34 /**
35  * Default constructor.
36  *
37  * @param owner True if we own and also delete the entities.
38  */
39 EntityContainer::EntityContainer(EntityContainer * parent/*= NULL*/, bool owner/*= true*/):
40         Entity(parent), entityIterator(entities)
41 //NOTE: This constructor may not be explicitly OR implicitly called, meaning that
42 //      entityIterator will not get initialized!
43 {
44 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
45 //    entities.setAutoDelete(owner);
46         DEBUG->print("EntityContainer::EntityContainer: owner: %d", (int)owner);
47     subContainer = NULL;
48     //autoUpdateBorders = true;
49 }
50
51 /**
52  * Copy constructor. Makes a deep copy of all entities.
53  */
54 /*
55 EntityContainer::EntityContainer(const EntityContainer& ec)
56  : Entity(ec)
57 {
58 }
59 */
60
61 /**
62  * Destructor.
63  */
64 EntityContainer::~EntityContainer()
65 {
66         clear();
67 }
68
69 Entity * EntityContainer::clone()
70 {
71 //      DEBUG->print("EntityContainer::clone: ori autoDel: %d", entities.autoDelete());
72         EntityContainer * ec = new EntityContainer(*this);
73 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
74 //      ec->entities.setAutoDelete(entities.autoDelete());
75 //      DEBUG->print("EntityContainer::clone: clone autoDel: %d", ec->entities.autoDelete());
76         ec->detach();
77         ec->initId();
78
79         return ec;
80 }
81
82 /**
83  * Detaches shallow copies and creates deep copies of all subentities.
84  * This is called after cloning entity containers.
85  */
86 void EntityContainer::detach()
87 {
88 //    Q3PtrList<Entity> tmp;
89         QList<Entity *> tmp;
90 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
91 //      bool autoDel = entities.autoDelete();
92 //      DEBUG->print("EntityContainer::detach: autoDel: %d", (int)autoDel);
93 //      entities.setAutoDelete(false);
94
95         // make deep copies of all entities:
96         for(Entity * e=firstEntity(); e!=NULL; e=nextEntity())
97         {
98                 if (!e->getFlag(RS2::FlagTemp))
99                 {
100                         tmp.append(e->clone());
101                 }
102         }
103
104         // clear shared pointers:
105         entities.clear();
106 //      entities.setAutoDelete(autoDel);
107
108         // point to new deep copies:
109 //      for(Entity * e=tmp.first(); e!=NULL; e=tmp.next())
110         for(int i=0; i<tmp.size(); i++)
111         {
112                 Entity * e = tmp[i];
113                 entities.append(e);
114                 e->reparent(this);
115         }
116 }
117
118 /** @return RS2::EntityContainer */
119 /*virtual*/ RS2::EntityType EntityContainer::rtti() const
120 {
121         return RS2::EntityContainer;
122 }
123
124 void EntityContainer::reparent(EntityContainer * parent)
125 {
126     Entity::reparent(parent);
127
128     // All sub-entities:
129     for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
130         {
131         e->reparent(parent);
132     }
133 }
134
135 /**
136  * @return true: because entities made from this class
137  *         and subclasses are containers for other entities.
138  */
139 /*virtual*/ bool EntityContainer::isContainer() const
140 {
141         return true;
142 }
143
144 /**
145  * @return false: because entities made from this class
146  *         and subclasses are containers for other entities.
147  */
148 /*virtual*/ bool EntityContainer::isAtomic() const
149 {
150         return false;
151 }
152
153 /**
154  * Called when the undo state changed. Forwards the event to all sub-entities.
155  *
156  * @param undone true: entity has become invisible.
157  *               false: entity has become visible.
158  */
159 void EntityContainer::undoStateChanged(bool undone)
160 {
161     Entity::undoStateChanged(undone);
162
163     // ! don't pass on to subentities. undo list handles them
164     // All sub-entities:
165     /*for (Entity* e=firstEntity(RS2::ResolveNone);
166             e!=NULL;
167             e=nextEntity(RS2::ResolveNone)) {
168         e->setUndoState(undone);
169 }*/
170 }
171
172 void EntityContainer::setVisible(bool v)
173 {
174     DEBUG->print("EntityContainer::setVisible: %d", v);
175     Entity::setVisible(v);
176
177     // All sub-entities:
178     for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
179         {
180         DEBUG->print("EntityContainer::setVisible: subentity: %d", v);
181         e->setVisible(v);
182     }
183 }
184
185 /**
186  * @return Total length of all entities in this container.
187  */
188 double EntityContainer::getLength()
189 {
190         double ret = 0.0;
191
192         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
193         {
194                 if (e->isVisible())
195                 {
196                         double l = e->getLength();
197
198                         if (l < 0.0)
199                         {
200                                 ret = -1.0;
201                                 break;
202                         }
203                         else
204                         {
205                                 ret += l;
206                         }
207                 }
208         }
209
210         return ret;
211 }
212
213 /**
214  * Selects this entity.
215  */
216 bool EntityContainer::setSelected(bool select)
217 {
218         // This entity's select:
219         if (Entity::setSelected(select))
220         {
221                 // All sub-entity's select:
222                 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
223                 {
224                         if (e->isVisible())
225                         {
226                                 e->setSelected(select);
227                         }
228                 }
229
230                 return true;
231         }
232         else
233         {
234                 return false;
235         }
236 }
237
238 /**
239  * Toggles select on this entity.
240  */
241 bool EntityContainer::toggleSelected()
242 {
243         // Toggle this entity's select:
244         if (Entity::toggleSelected())
245         {
246
247                 // Toggle all sub-entity's select:
248                 /*for (Entity* e=firstEntity(RS2::ResolveNone);
249                                 e!=NULL;
250                                 e=nextEntity(RS2::ResolveNone)) {
251                         e->toggleSelected();
252         }*/
253                 return true;
254         }
255         else
256         {
257                 return false;
258         }
259 }
260
261 /**
262  * Selects all entities within the given area.
263  *
264  * @param select True to select, False to deselect the entities.
265  */
266 void EntityContainer::selectWindow(Vector v1, Vector v2, bool select, bool cross)
267 {
268         bool included;
269
270         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
271         {
272                 included = false;
273
274                 if (e->isVisible())
275                 {
276                         if (e->isInWindow(v1, v2))
277                         {
278                                 //e->setSelected(select);
279                                 included = true;
280                         }
281                         else if (cross == true)
282                         {
283                                 Line l[] =
284                                         {
285                                                 Line(NULL, LineData(v1, Vector(v2.x, v1.y))),
286                                                 Line(NULL, LineData(Vector(v2.x, v1.y), v2)),
287                                                 Line(NULL, LineData(v2, Vector(v1.x, v2.y))),
288                                                 Line(NULL, LineData(Vector(v1.x, v2.y), v1))
289                                         };
290                                 VectorSolutions sol;
291
292                                 if (e->isContainer())
293                                 {
294                                         EntityContainer * ec = (EntityContainer *)e;
295
296                                         for(Entity * se=ec->firstEntity(RS2::ResolveAll); se!=NULL && included==false;
297                                                 se=ec->nextEntity(RS2::ResolveAll))
298                                         {
299                                                 for(int i=0; i<4; ++i)
300                                                 {
301                                                         sol = Information::getIntersection(se, &l[i], true);
302
303                                                         if (sol.hasValid())
304                                                         {
305                                                                 included = true;
306                                                                 break;
307                                                         }
308                                                 }
309                                         }
310                                 }
311                                 else
312                                 {
313                                         for(int i=0; i<4; ++i)
314                                         {
315                                                 sol = Information::getIntersection(e, &l[i], true);
316
317                                                 if (sol.hasValid())
318                                                 {
319                                                         included = true;
320                                                         break;
321                                                 }
322                                         }
323                                 }
324                         }
325                 }
326
327                 if (included)
328                 {
329                         e->setSelected(select);
330                 }
331         }
332 }
333
334 /**
335  * Adds a entity to this container and updates the borders of this
336  * entity-container if autoUpdateBorders is true.
337  */
338 void EntityContainer::addEntity(Entity * entity)
339 {
340         /*
341                 if (isDocument()) {
342                         LayerList* lst = getDocument()->getLayerList();
343                         if (lst!=NULL) {
344                                 Layer* l = lst->getActive();
345                                 if (l!=NULL && l->isLocked()) {
346                                         return;
347                                 }
348                         }
349                 }
350         */
351 //printf("EntityContainer::addEntity(): entity=%08X\n", entity);
352
353         if (!entity)
354                 return;
355
356         if (entity->rtti() == RS2::EntityImage || entity->rtti() == RS2::EntityHatch)
357                 entities.prepend(entity);
358         else
359                 entities.append(entity);
360
361         if (autoUpdateBorders)
362                 adjustBorders(entity);
363 //printf("                                 # of entities=%d\n", entities.size());
364 }
365
366 /**
367  * Inserts a entity to this container at the given position and updates
368  * the borders of this entity-container if autoUpdateBorders is true.
369  */
370 void EntityContainer::insertEntity(int index, Entity * entity)
371 {
372         if (entity == NULL)
373                 return;
374
375         entities.insert(index, entity);
376
377         if (autoUpdateBorders)
378                 adjustBorders(entity);
379 }
380
381 /**
382  * Replaces the entity at the given index with the given entity
383  * and updates the borders of this entity-container if autoUpdateBorders is true.
384  */
385 void EntityContainer::replaceEntity(int index, Entity * entity)
386 {
387         if (entity == NULL)
388                 return;
389
390         entities.replace(index, entity);
391
392         if (autoUpdateBorders)
393                 adjustBorders(entity);
394 }
395
396 /**
397  * Removes an entity from this container and updates the borders of
398  * this entity-container if autoUpdateBorders is true.
399  */
400 bool EntityContainer::removeEntity(Entity * entity)
401 {
402 //      bool ret = entities.remove(entity);
403         bool ret = (bool)entities.removeAll(entity);
404
405         if (autoUpdateBorders)
406                 calculateBorders();
407
408         return ret;
409 }
410
411 /**
412  * Erases all entities in this container and resets the borders..
413  */
414 void EntityContainer::clear()
415 {
416         entities.clear();
417         resetBorders();
418 }
419
420 /**
421  * Counts all entities (branches of the tree).
422  */
423 unsigned long int EntityContainer::count()
424 {
425         return entities.count();
426 }
427
428 /**
429  * Counts all entities (leaves of the tree).
430  */
431 unsigned long int EntityContainer::countDeep()
432 {
433         unsigned long int c = 0;
434
435         for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
436         {
437                 c += t->countDeep();
438         }
439
440         return c;
441 }
442
443 /**
444  * Counts the selected entities in this container.
445  */
446 unsigned long int EntityContainer::countSelected()
447 {
448         unsigned long int c = 0;
449
450         for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
451         {
452                 if (t->isSelected())
453                 {
454                         c++;
455                 }
456         }
457
458         return c;
459 }
460
461 /**
462  * Enables / disables automatic update of borders on entity removals
463  * and additions. By default this is turned on.
464  */
465 /*virtual*/ void EntityContainer::setAutoUpdateBorders(bool enable)
466 {
467         autoUpdateBorders = enable;
468 }
469
470 /**
471  * Adjusts the borders of this graphic (max/min values)
472  */
473 void EntityContainer::adjustBorders(Entity * entity)
474 {
475         //DEBUG->print("EntityContainer::adjustBorders");
476         //resetBorders();
477
478         if (entity != NULL)
479         {
480                 // make sure a container is not empty (otherwise the border
481                 //   would get extended to 0/0):
482                 if (!entity->isContainer() || entity->count() > 0)
483                 {
484                         minV = Vector::minimum(entity->getMin(), minV);
485                         maxV = Vector::maximum(entity->getMax(), maxV);
486                 }
487
488                 // Notify parents. The border for the parent might
489                 // also change TODO: Check for efficiency
490                 //if(parent!=NULL) {
491                 //parent->adjustBorders(this);
492                 //}
493         }
494 }
495
496 /**
497  * Recalculates the borders of this entity container.
498  */
499 void EntityContainer::calculateBorders()
500 {
501         DEBUG->print("EntityContainer::calculateBorders");
502
503         resetBorders();
504
505         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
506         {
507                 Layer * layer = e->getLayer();
508
509                 DEBUG->print("EntityContainer::calculateBorders: isVisible: %d", (int)e->isVisible());
510
511                 if (e->isVisible() && (layer == NULL || !layer->isFrozen()))
512                 {
513                         e->calculateBorders();
514                         adjustBorders(e);
515                 }
516         }
517
518         DEBUG->print("EntityContainer::calculateBorders: size 1: %f,%f", getSize().x, getSize().y);
519
520         // needed for correcting corrupt data (PLANS.dxf)
521         if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
522                 || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
523         {
524                 minV.x = 0.0;
525                 maxV.x = 0.0;
526         }
527
528         if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
529                 || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
530         {
531                 minV.y = 0.0;
532                 maxV.y = 0.0;
533         }
534
535         DEBUG->print("EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y);
536
537         //DEBUG->print("  borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
538
539         //printf("borders: %lf/%lf  %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
540         //Entity::calculateBorders();
541 }
542
543 /**
544  * Recalculates the borders of this entity container including
545  * invisible entities.
546  */
547 void EntityContainer::forcedCalculateBorders()
548 {
549         //DEBUG->print("EntityContainer::calculateBorders");
550
551         resetBorders();
552
553         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
554         {
555                 //Layer* layer = e->getLayer();
556
557                 if (e->isContainer())
558                 {
559                         ((EntityContainer *)e)->forcedCalculateBorders();
560                 }
561                 else
562                 {
563                         e->calculateBorders();
564                 }
565
566                 adjustBorders(e);
567         }
568
569         // needed for correcting corrupt data (PLANS.dxf)
570         if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
571                 || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
572         {
573                 minV.x = 0.0;
574                 maxV.x = 0.0;
575         }
576
577         if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
578                 || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
579         {
580                 minV.y = 0.0;
581                 maxV.y = 0.0;
582         }
583
584         //DEBUG->print("  borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
585
586         //printf("borders: %lf/%lf  %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
587         //Entity::calculateBorders();
588 }
589
590 /**
591  * Updates all Dimension entities in this container and
592  * reposition their labels.
593  */
594 void EntityContainer::updateDimensions()
595 {
596         DEBUG->print("EntityContainer::updateDimensions()");
597
598         //for (Entity* e=firstEntity(RS2::ResolveNone);
599         //        e!=NULL;
600         //        e=nextEntity(RS2::ResolveNone)) {
601
602 #if 0
603 //      Q3PtrListIterator<Entity> it = createIterator();
604         QListIterator<Entity *> it = createIterator();
605 //      return QListIterator<Entity *>(entities);
606
607         Entity * e;
608
609         while ((e = it.current()) != NULL)
610         {
611                 ++it;
612
613                 if (Information::isDimension(e->rtti()))
614                 {
615                         // update and reposition label:
616                         ((Dimension *)e)->update(true);
617                 }
618                 else if (e->isContainer())
619                 {
620                         ((EntityContainer *)e)->updateDimensions();
621                 }
622         }
623 #else
624         for(int i=0; i<entities.size(); i++)
625         {
626                 Entity * e = entities[i];
627
628                 if (Information::isDimension(e->rtti()))
629                         // update and reposition label:
630                         ((Dimension *)e)->update(true);
631                 else if (e->isContainer())
632                         ((EntityContainer *)e)->updateDimensions();
633         }
634 #endif
635
636         DEBUG->print("EntityContainer::updateDimensions() OK");
637 }
638
639 /**
640  * Updates all Insert entities in this container.
641  */
642 void EntityContainer::updateInserts()
643 {
644         DEBUG->print("EntityContainer::updateInserts()");
645
646         //for (Entity* e=firstEntity(RS2::ResolveNone);
647         //        e!=NULL;
648         //        e=nextEntity(RS2::ResolveNone)) {
649 #if 0
650         Q3PtrListIterator<Entity> it = createIterator();
651         Entity * e;
652
653         while ((e = it.current()) != NULL)
654         {
655                 ++it;
656                 //// Only update our own inserts and not inserts of inserts
657                 if (e->rtti() == RS2::EntityInsert  /*&& e->getParent()==this*/)
658                 {
659                         ((Insert *)e)->update();
660                 }
661                 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
662                 {
663                         ((EntityContainer *)e)->updateInserts();
664                 }
665         }
666 #else
667         for(int i=0; i<entities.size(); i++)
668         {
669                 Entity * e = entities[i];
670
671                 //// Only update our own inserts and not inserts of inserts
672                 if (e->rtti() == RS2::EntityInsert  /*&& e->getParent()==this*/)
673                         ((Insert *)e)->update();
674                 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
675                         ((EntityContainer *)e)->updateInserts();
676         }
677 #endif
678
679         DEBUG->print("EntityContainer::updateInserts() OK");
680 }
681
682 /**
683  * Renames all inserts with name 'oldName' to 'newName'. This is
684  *   called after a block was rename to update the inserts.
685  */
686 void EntityContainer::renameInserts(const QString& oldName, const QString& newName)
687 {
688     DEBUG->print("EntityContainer::renameInserts()");
689
690     //for (Entity* e=firstEntity(RS2::ResolveNone);
691     //        e!=NULL;
692     //        e=nextEntity(RS2::ResolveNone)) {
693
694 #if 0
695     Q3PtrListIterator<Entity> it = createIterator();
696     Entity* e;
697     while ( (e = it.current()) != NULL ) {
698         ++it;
699
700         if (e->rtti()==RS2::EntityInsert) {
701             Insert* i = ((Insert*)e);
702             if (i->getName()==oldName) {
703                 i->setName(newName);
704             }
705         } else if (e->isContainer()) {
706             ((EntityContainer*)e)->renameInserts(oldName, newName);
707         }
708     }
709 #else
710         for(int i=0; i<entities.size(); i++)
711         {
712                 Entity * e = entities[i];
713
714         if (e->rtti() == RS2::EntityInsert)
715                 {
716             Insert * i = ((Insert *)e);
717
718                         if (i->getName() == oldName)
719                 i->setName(newName);
720         }
721         else if (e->isContainer())
722             ((EntityContainer *)e)->renameInserts(oldName, newName);
723         }
724 #endif
725
726     DEBUG->print("EntityContainer::renameInserts() OK");
727
728 }
729
730 /**
731  * Updates all Spline entities in this container.
732  */
733 void EntityContainer::updateSplines()
734 {
735     DEBUG->print("EntityContainer::updateSplines()");
736
737     //for (Entity* e=firstEntity(RS2::ResolveNone);
738     //        e!=NULL;
739     //        e=nextEntity(RS2::ResolveNone)) {
740 #if 0
741     Q3PtrListIterator<Entity> it = createIterator();
742     Entity* e;
743     while ( (e = it.current()) != NULL ) {
744         ++it;
745         //// Only update our own inserts and not inserts of inserts
746         if (e->rtti()==RS2::EntitySpline  /*&& e->getParent()==this*/) {
747             ((Spline*)e)->update();
748         } else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) {
749             ((EntityContainer*)e)->updateSplines();
750         }
751     }
752 #else
753         for(int i=0; i<entities.size(); i++)
754         {
755                 Entity * e = entities[i];
756
757                 //// Only update our own inserts and not inserts of inserts
758                 if (e->rtti() == RS2::EntitySpline  /*&& e->getParent()==this*/)
759                         ((Spline *)e)->update();
760                 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
761                         ((EntityContainer *)e)->updateSplines();
762         }
763 #endif
764
765     DEBUG->print("EntityContainer::updateSplines() OK");
766 }
767
768 /**
769  * Updates the sub entities of this container.
770  */
771 void EntityContainer::update()
772 {
773     //for (Entity* e=firstEntity(RS2::ResolveNone);
774     //        e!=NULL;
775     //        e=nextEntity(RS2::ResolveNone)) {
776 #if 0
777     Q3PtrListIterator<Entity> it = createIterator();
778     Entity* e;
779     while ( (e = it.current()) != NULL ) {
780         ++it;
781         e->update();
782     }
783 #else
784         for(int i=0; i<entities.size(); i++)
785         {
786 //              Entity * e = entities[i];
787 //              e->update();
788                 entities[i]->update();
789         }
790 #endif
791 }
792
793 /**
794  * Returns the first entity or NULL if this graphic is empty.
795  * @param level
796  */
797 Entity * EntityContainer::firstEntity(RS2::ResolveLevel level)
798 {
799         switch (level)
800         {
801         case RS2::ResolveNone:
802 //              return entities.first();
803 //              entityIterator.toFront();
804                 entityIterator = entities;
805                 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
806                 break;
807
808         case RS2::ResolveAllButInserts:
809         {
810                 subContainer = NULL;
811 //              Entity * e = entities.first();
812 //              entityIterator.toFront();
813                 entityIterator = entities;
814                 Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
815
816                 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
817                 {
818                         subContainer = (EntityContainer *)e;
819                         e = ((EntityContainer *)e)->firstEntity(level);
820
821                         // emtpy container:
822                         if (e == NULL)
823                         {
824                                 subContainer = NULL;
825                                 e = nextEntity(level);
826                         }
827                 }
828
829                 return e;
830         }
831                 break;
832
833         case RS2::ResolveAll:
834         {
835                 subContainer = NULL;
836 //              Entity * e = entities.first();
837 //              entityIterator.toFront();
838                 entityIterator = entities;
839                 Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
840
841                 if (e != NULL && e->isContainer())
842                 {
843                         subContainer = (EntityContainer *)e;
844                         e = ((EntityContainer *)e)->firstEntity(level);
845
846                         // emtpy container:
847                         if (e == NULL)
848                         {
849                                 subContainer = NULL;
850                                 e = nextEntity(level);
851                         }
852                 }
853
854                 return e;
855         }
856                 break;
857         }
858
859         return NULL;
860 }
861
862 /**
863  * Returns the last entity or \p NULL if this graphic is empty.
864  *
865  * @param level \li \p 0 Groups are not resolved
866  *              \li \p 1 (default) only Groups are resolved
867  *              \li \p 2 all Entity Containers are resolved
868  */
869 Entity * EntityContainer::lastEntity(RS2::ResolveLevel level)
870 {
871         switch (level)
872         {
873         case RS2::ResolveNone:
874 //              return entities.last();
875                 entityIterator = entities;
876                 entityIterator.toBack();
877                 return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
878                 break;
879
880         case RS2::ResolveAllButInserts:
881         {
882 //              Entity * e = entities.last();
883                 entityIterator = entities;
884                 entityIterator.toBack();
885                 Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
886                 subContainer = NULL;
887
888                 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
889                 {
890                         subContainer = (EntityContainer *)e;
891                         e = ((EntityContainer *)e)->lastEntity(level);
892                 }
893
894                 return e;
895         }
896                 break;
897
898         case RS2::ResolveAll:
899         {
900 //              Entity * e = entities.last();
901                 entityIterator = entities;
902                 entityIterator.toBack();
903                 Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
904                 subContainer = NULL;
905
906                 if (e != NULL && e->isContainer())
907                 {
908                         subContainer = (EntityContainer *)e;
909                         e = ((EntityContainer *)e)->lastEntity(level);
910                 }
911
912                 return e;
913         }
914                 break;
915         }
916
917         return NULL;
918 }
919
920 /**
921  * Returns the next entity or container or \p NULL if the last entity
922  * returned by \p next() was the last entity in the container.
923  */
924 Entity * EntityContainer::nextEntity(RS2::ResolveLevel level)
925 {
926         switch (level)
927         {
928         case RS2::ResolveNone:
929 //              return entities.next();
930                 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
931                 break;
932
933         case RS2::ResolveAllButInserts:
934         {
935                 Entity * e = NULL;
936
937                 if (subContainer != NULL)
938                 {
939                         e = subContainer->nextEntity(level);
940
941                         if (e != NULL)
942                         {
943                                 return e;
944                         }
945                         else
946                         {
947 //                              e = entities.next();
948                                 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
949                         }
950                 }
951                 else
952                 {
953 //                      e = entities.next();
954                         e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
955                 }
956
957                 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
958                 {
959                         subContainer = (EntityContainer *)e;
960                         e = ((EntityContainer *)e)->firstEntity(level);
961
962                         // emtpy container:
963                         if (e == NULL)
964                         {
965                                 subContainer = NULL;
966                                 e = nextEntity(level);
967                         }
968                 }
969
970                 return e;
971         }
972                 break;
973
974         case RS2::ResolveAll:
975         {
976                 Entity * e = NULL;
977
978                 if (subContainer != NULL)
979                 {
980                         e = subContainer->nextEntity(level);
981
982                         if (e != NULL)
983                                 return e;
984                         else
985 //                              e = entities.next();
986                                 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
987                 }
988                 else
989                 {
990 //                      e = entities.next();
991                         e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
992                 }
993
994                 if (e != NULL && e->isContainer())
995                 {
996                         subContainer = (EntityContainer *)e;
997                         e = ((EntityContainer *)e)->firstEntity(level);
998
999                         // emtpy container:
1000                         if (e == NULL)
1001                         {
1002                                 subContainer = NULL;
1003                                 e = nextEntity(level);
1004                         }
1005                 }
1006
1007                 return e;
1008         }
1009                 break;
1010         }
1011         return NULL;
1012 }
1013
1014 /**
1015  * Returns the prev entity or container or \p NULL if the last entity
1016  * returned by \p prev() was the first entity in the container.
1017  */
1018 Entity * EntityContainer::prevEntity(RS2::ResolveLevel level)
1019 {
1020         Entity * e = NULL;
1021
1022         switch (level)
1023         {
1024         case RS2::ResolveNone:
1025 //              return entities.prev();
1026                 return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1027                 break;
1028
1029         case RS2::ResolveAllButInserts:
1030                 e = NULL;
1031
1032                 if (subContainer != NULL)
1033                 {
1034                         e = subContainer->prevEntity(level);
1035
1036                         if (e != NULL)
1037                                 return e;
1038                         else
1039 //                              e = entities.prev();
1040                                 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1041                 }
1042                 else
1043                 {
1044 //                      e = entities.prev();
1045                         e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1046                 }
1047
1048                 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
1049                 {
1050                         subContainer = (EntityContainer *)e;
1051                         e = ((EntityContainer *)e)->lastEntity(level);
1052
1053                         // emtpy container:
1054                         if (e == NULL)
1055                         {
1056                                 subContainer = NULL;
1057                                 e = prevEntity(level);
1058                         }
1059                 }
1060
1061                 return e;
1062
1063         case RS2::ResolveAll:
1064                 e = NULL;
1065
1066                 if (subContainer != NULL)
1067                 {
1068                         e = subContainer->prevEntity(level);
1069
1070                         if (e != NULL)
1071                                 return e;
1072                         else
1073 //                              e = entities.prev();
1074                                 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1075                 }
1076                 else
1077                 {
1078 //                      e = entities.prev();
1079                         e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1080                 }
1081
1082                 if (e != NULL && e->isContainer())
1083                 {
1084                         subContainer = (EntityContainer *)e;
1085                         e = ((EntityContainer *)e)->lastEntity(level);
1086
1087                         // emtpy container:
1088                         if (e == NULL)
1089                         {
1090                                 subContainer = NULL;
1091                                 e = prevEntity(level);
1092                         }
1093                 }
1094
1095                 return e;
1096         }
1097
1098         return NULL;
1099 }
1100
1101 /**
1102  * @return Entity at the given index or NULL if the index is out of range.
1103  */
1104 Entity * EntityContainer::entityAt(uint index)
1105 {
1106         return entities.at(index);
1107 }
1108
1109 /**
1110  * @return Current index.
1111  */
1112 int EntityContainer::entityAt()
1113 {
1114 #warning "!!! Not sure how to convert this from Qt3 -> Qt4 !!! (it seems we can ignore this for now as nothing calls it)"
1115 //      return entities.at();
1116         return 0;
1117 }
1118
1119 /**
1120  * Finds the given entity and makes it the current entity if found.
1121  */
1122 int EntityContainer::findEntity(Entity * entity)
1123 {
1124 //      return entities.find(entity);
1125
1126         entityIterator.toFront();
1127         entityIterator.findNext(entity);
1128
1129         return entities.indexOf(entity);
1130 }
1131
1132 /**
1133  * @return The current entity.
1134  */
1135 Entity * EntityContainer::currentEntity()
1136 {
1137 //      return entities.current();
1138
1139 // We really need to refactor this crap, this is the way it is now to support
1140 // the old broken way of doing things
1141         return entityIterator.peekNext();
1142 }
1143
1144 #if 0
1145 #warning "!!! Not needed anymore !!!"
1146 /**
1147  * Returns the copy to a new iterator for traversing the entities.
1148  */
1149 //Q3PtrListIterator<Entity> EntityContainer::createIterator()
1150 QListIterator<Entity *> EntityContainer::createIterator()
1151 {
1152 //      return Q3PtrListIterator<Entity>(entities);
1153         return QListIterator<Entity *>(entities);
1154 }
1155 #endif
1156
1157 /*virtual*/ bool EntityContainer::isEmpty()
1158 {
1159         return (count() == 0);
1160 }
1161
1162 /**
1163  * @return The point which is closest to 'coord'
1164  * (one of the vertexes)
1165  */
1166 Vector EntityContainer::getNearestEndpoint(const Vector & coord, double * dist)
1167 {
1168     double minDist = RS_MAXDOUBLE;  // minimum measured distance
1169     double curDist;                 // currently measured distance
1170     Vector closestPoint(false);  // closest found endpoint
1171     Vector point;                // endpoint found
1172
1173     //Q3PtrListIterator<Entity> it = createIterator();
1174     //Entity* en;
1175     //while ( (en = it.current()) != NULL ) {
1176     //    ++it;
1177     for (Entity* en = firstEntity();
1178             en != NULL;
1179             en = nextEntity()) {
1180
1181         if (en->isVisible()) {
1182             point = en->getNearestEndpoint(coord, &curDist);
1183             if (point.valid && curDist<minDist) {
1184                 closestPoint = point;
1185                 minDist = curDist;
1186                 if (dist!=NULL) {
1187                     *dist = curDist;
1188                 }
1189             }
1190         }
1191     }
1192
1193     return closestPoint;
1194 }
1195
1196 Vector EntityContainer::getNearestPointOnEntity(const Vector & coord,
1197         bool onEntity, double * dist, Entity ** entity)
1198 {
1199         Vector point(false);
1200
1201         Entity * e = getNearestEntity(coord, dist, RS2::ResolveNone);
1202
1203         if (e && e->isVisible())
1204                 point = e->getNearestPointOnEntity(coord, onEntity, dist, entity);
1205
1206         return point;
1207 }
1208
1209 Vector EntityContainer::getNearestCenter(const Vector & coord, double * dist)
1210 {
1211         Vector point(false);
1212         Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1213
1214         if (closestEntity)
1215                 point = closestEntity->getNearestCenter(coord, dist);
1216
1217         return point;
1218 }
1219
1220 Vector EntityContainer::getNearestMiddle(const Vector & coord, double * dist)
1221 {
1222         Vector point(false);
1223         Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1224
1225         if (closestEntity)
1226                 point = closestEntity->getNearestMiddle(coord, dist);
1227
1228         return point;
1229 }
1230
1231 Vector EntityContainer::getNearestDist(double distance, const Vector & coord,
1232         double * dist)
1233 {
1234         Vector point(false);
1235         Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1236
1237         if (closestEntity)
1238                 point = closestEntity->getNearestDist(distance, coord, dist);
1239
1240         return point;
1241 }
1242
1243 /**
1244  * @return The intersection which is closest to 'coord'
1245  */
1246 Vector EntityContainer::getNearestIntersection(const Vector & coord,
1247         double * dist)
1248 {
1249         double minDist = RS_MAXDOUBLE;                          // minimum measured distance
1250         double curDist;                                                         // currently measured distance
1251         Vector closestPoint(false);                                     // closest found endpoint
1252         Vector point;                                                           // endpoint found
1253         VectorSolutions sol;
1254         Entity * closestEntity;
1255
1256         closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
1257
1258         if (closestEntity)
1259         {
1260                 for(Entity * en=firstEntity(RS2::ResolveAll); en!=NULL;
1261                         en = nextEntity(RS2::ResolveAll))
1262                 {
1263                         if (en->isVisible() && en!=closestEntity)
1264                         {
1265                                 sol = Information::getIntersection(closestEntity, en, true);
1266
1267                                 for(int i=0; i<4; i++)
1268                                 {
1269                                         point = sol.get(i);
1270
1271                                         if (point.valid)
1272                                         {
1273                                                 curDist = coord.distanceTo(point);
1274
1275                                                 if (curDist < minDist)
1276                                                 {
1277                                                         closestPoint = point;
1278                                                         minDist = curDist;
1279
1280                                                         if (dist)
1281                                                                 *dist = curDist;
1282                                                 }
1283                                         }
1284                                 }
1285                         }
1286                 }
1287         }
1288
1289         return closestPoint;
1290 }
1291
1292 Vector EntityContainer::getNearestRef(const Vector & coord, double * dist)
1293 {
1294         double minDist = RS_MAXDOUBLE;  // minimum measured distance
1295         double curDist;                 // currently measured distance
1296         Vector closestPoint(false);  // closest found endpoint
1297         Vector point;                // endpoint found
1298
1299         for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1300         {
1301                 if (en->isVisible())
1302                 {
1303                         point = en->getNearestRef(coord, &curDist);
1304
1305                         if (point.valid && curDist < minDist)
1306                         {
1307                                 closestPoint = point;
1308                                 minDist = curDist;
1309
1310                                 if (dist)
1311                                         *dist = curDist;
1312                         }
1313                 }
1314         }
1315
1316         return closestPoint;
1317 }
1318
1319 Vector EntityContainer::getNearestSelectedRef(const Vector & coord,
1320         double * dist)
1321 {
1322         double minDist = RS_MAXDOUBLE;                          // minimum measured distance
1323         double curDist;                                                         // currently measured distance
1324         Vector closestPoint(false);                                     // closest found endpoint
1325         Vector point;                                                           // endpoint found
1326
1327         for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1328         {
1329                 if (en->isVisible() && en->isSelected() && !en->isParentSelected())
1330                 {
1331                         point = en->getNearestSelectedRef(coord, &curDist);
1332
1333                         if (point.valid && curDist < minDist)
1334                         {
1335                                 closestPoint = point;
1336                                 minDist = curDist;
1337
1338                                 if (dist)
1339                                         *dist = curDist;
1340                         }
1341                 }
1342         }
1343
1344         return closestPoint;
1345 }
1346
1347 double EntityContainer::getDistanceToPoint(const Vector & coord,
1348         Entity ** entity, RS2::ResolveLevel level, double solidDist)
1349 {
1350         DEBUG->print("EntityContainer::getDistanceToPoint");
1351
1352         double minDist = RS_MAXDOUBLE;      // minimum measured distance
1353         double curDist;                     // currently measured distance
1354         Entity * closestEntity = NULL;    // closest entity found
1355         Entity * subEntity = NULL;
1356
1357         //int k=0;
1358         for(Entity * e=firstEntity(level); e!=NULL; e=nextEntity(level))
1359         {
1360                 if (e->isVisible())
1361                 {
1362                         DEBUG->print("entity: getDistanceToPoint");
1363                         DEBUG->print("entity: %d", e->rtti());
1364                         curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist);
1365                         DEBUG->print("entity: getDistanceToPoint: OK");
1366
1367                         if (curDist<minDist)
1368                         {
1369                                 if (level != RS2::ResolveAll)
1370                                         closestEntity = e;
1371                                 else
1372                                         closestEntity = subEntity;
1373
1374                                 minDist = curDist;
1375                         }
1376                 }
1377         }
1378
1379         if (entity)
1380                 *entity = closestEntity;
1381
1382         DEBUG->print("EntityContainer::getDistanceToPoint: OK");
1383         return minDist;
1384 }
1385
1386 Entity * EntityContainer::getNearestEntity(const Vector & coord,
1387         double * dist, RS2::ResolveLevel level)
1388 {
1389         DEBUG->print("EntityContainer::getNearestEntity");
1390         Entity * e = NULL;
1391
1392         // distance for points inside solids:
1393         double solidDist = RS_MAXDOUBLE;
1394
1395         if (dist)
1396                 solidDist = *dist;
1397
1398         double d = getDistanceToPoint(coord, &e, level, solidDist);
1399
1400         if (e && e->isVisible() == false)
1401                 e = NULL;
1402
1403         // if d is negative, use the default distance (used for points inside solids)
1404         if (dist)
1405                 *dist = d;
1406
1407         DEBUG->print("EntityContainer::getNearestEntity: OK");
1408         return e;
1409 }
1410
1411 /**
1412  * Rearranges the atomic entities in this container in a way that connected
1413  * entities are stored in the right order and direction.
1414  * Non-recoursive. Only affects atomic entities in this container.
1415  *
1416  * @retval true all contours were closed
1417  * @retval false at least one contour is not closed
1418  */
1419 bool EntityContainer::optimizeContours()
1420 {
1421         DEBUG->print("EntityContainer::optimizeContours");
1422
1423         Vector current(false);
1424         Vector start(false);
1425         EntityContainer tmp;
1426
1427         bool changed = false;
1428         bool closed = true;
1429
1430         for(uint ci=0; ci<count(); ++ci)
1431         {
1432                 Entity * e1=entityAt(ci);
1433
1434                 if (e1 && e1->isEdge() && !e1->isContainer() && !e1->isProcessed())
1435                 {
1436                         AtomicEntity * ce = (AtomicEntity *)e1;
1437
1438                         // next contour start:
1439                         ce->setProcessed(true);
1440                         tmp.addEntity(ce->clone());
1441                         current = ce->getEndpoint();
1442                         start = ce->getStartpoint();
1443
1444                         // find all connected entities:
1445                         bool done;
1446
1447                         do
1448                         {
1449                                 done = true;
1450                                 for(uint ei=0; ei<count(); ++ei)
1451                                 {
1452                                         Entity * e2=entityAt(ei);
1453
1454                                         if (e2 != NULL && e2->isEdge() && !e2->isContainer() &&
1455                                                 !e2->isProcessed())
1456                                         {
1457                                                 AtomicEntity * e = (AtomicEntity *)e2;
1458
1459                                                 if (e->getStartpoint().distanceTo(current) < 1.0e-4)
1460                                                 {
1461                                                         e->setProcessed(true);
1462                                                         tmp.addEntity(e->clone());
1463                                                         current = e->getEndpoint();
1464                                                         done = false;
1465                                                 }
1466                                                 else if (e->getEndpoint().distanceTo(current) < 1.0e-4)
1467                                                 {
1468                                                         e->setProcessed(true);
1469                                                         AtomicEntity * cl = (AtomicEntity *)e->clone();
1470                                                         cl->reverse();
1471                                                         tmp.addEntity(cl);
1472                                                         current = cl->getEndpoint();
1473                                                         changed = true;
1474                                                         done = false;
1475                                                 }
1476                                         }
1477                                 }
1478
1479                                 if (!done)
1480                                         changed = true;
1481                         }
1482                         while (!done);
1483
1484                         if (current.distanceTo(start) > 1.0e-4)
1485                                 closed = false;
1486                 }
1487         }
1488
1489         // remove all atomic entities:
1490         bool done;
1491
1492         do
1493         {
1494                 done = true;
1495
1496                 for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1497                 {
1498                         if (!en->isContainer())
1499                         {
1500                                 removeEntity(en);
1501                                 done = false;
1502                                 break;
1503                         }
1504                 }
1505         }
1506         while (!done);
1507
1508         // add new sorted entities:
1509         for(Entity * en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity())
1510         {
1511                 en->setProcessed(false);
1512                 addEntity(en->clone());
1513         }
1514
1515         DEBUG->print("EntityContainer::optimizeContours: OK");
1516         return closed;
1517 }
1518
1519 bool EntityContainer::hasEndpointsWithinWindow(Vector v1, Vector v2)
1520 {
1521         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1522         {
1523                 if (e->hasEndpointsWithinWindow(v1, v2))
1524                         return true;
1525         }
1526
1527         return false;
1528 }
1529
1530 void EntityContainer::move(Vector offset)
1531 {
1532         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1533                 e->move(offset);
1534
1535         if (autoUpdateBorders)
1536                 calculateBorders();
1537 }
1538
1539 void EntityContainer::rotate(Vector center, double angle)
1540 {
1541         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1542                 e->rotate(center, angle);
1543
1544         if (autoUpdateBorders)
1545                 calculateBorders();
1546 }
1547
1548 void EntityContainer::scale(Vector center, Vector factor)
1549 {
1550         if (fabs(factor.x) > RS_TOLERANCE && fabs(factor.y) > RS_TOLERANCE)
1551         {
1552                 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1553                         e->scale(center, factor);
1554         }
1555
1556         if (autoUpdateBorders)
1557                 calculateBorders();
1558 }
1559
1560 void EntityContainer::mirror(Vector axisPoint1, Vector axisPoint2)
1561 {
1562         if (axisPoint1.distanceTo(axisPoint2) > 1.0e-6)
1563         {
1564                 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1565                         e->mirror(axisPoint1, axisPoint2);
1566         }
1567 }
1568
1569 void EntityContainer::stretch(Vector firstCorner, Vector secondCorner,
1570         Vector offset)
1571 {
1572         if (getMin().isInWindow(firstCorner, secondCorner) &&
1573                 getMax().isInWindow(firstCorner, secondCorner))
1574         {
1575                 move(offset);
1576         }
1577         else
1578         {
1579                 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1580                         e->stretch(firstCorner, secondCorner, offset);
1581         }
1582
1583         // some entitiycontainers might need an update (e.g. Leader):
1584         update();
1585 }
1586
1587 void EntityContainer::moveRef(const Vector & ref, const Vector & offset)
1588 {
1589         for(Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1590                 e->moveRef(ref, offset);
1591
1592         if (autoUpdateBorders)
1593                 calculateBorders();
1594 }
1595
1596 void EntityContainer::moveSelectedRef(const Vector & ref, const Vector & offset)
1597 {
1598         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1599                 e->moveSelectedRef(ref, offset);
1600
1601         if (autoUpdateBorders)
1602                 calculateBorders();
1603 }
1604
1605 void EntityContainer::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
1606 {
1607         if (!painter || !view)
1608                 return;
1609
1610         for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1611 #if 0
1612 {
1613 if (e->rtti() == RS2::EntityText)
1614 {
1615         std::cout << "About to draw TEXT entity... "
1616                 << "TEXT=\"" << ((Text *)e)->getText().toAscii().data() << "\"" << std::endl;
1617 }
1618 //OK, we have text, but no insert entities at least none that are drawn...
1619 //Ah! But with a standard text entity, it DOES have them!
1620 else if (e->rtti() == RS2::EntityInsert)
1621 {
1622         std::cout << "About to draw INSERT entity... "
1623                 << "INSERT=\"" << ((Insert *)e)->getData().name.toAscii().data() << "\"" << std::endl;
1624 }
1625 #endif
1626                 view->drawEntity(e);
1627 #if 0
1628 }
1629 #endif
1630 }
1631
1632 /**
1633  * Dumps the entities to stdout.
1634  */
1635 std::ostream & operator<<(std::ostream & os, EntityContainer & ec)
1636 {
1637         static int indent = 0;
1638         char * tab = new char[indent * 2 + 1];
1639
1640         for(int i=0; i<indent*2; i++)
1641                 tab[i] = ' ';
1642
1643         tab[indent * 2] = '\0';
1644         indent++;
1645         unsigned long int id = ec.getId();
1646
1647         os << tab << "EntityContainer[" << id << "]: \n";
1648         os << tab << "Borders[" << id << "]: "
1649         << ec.minV << " - " << ec.maxV << "\n";
1650         //os << tab << "Unit[" << id << "]: "
1651         //<< Units::unit2string (ec.unit) << "\n";
1652         if (ec.getLayer())
1653         {
1654                 os << tab << "Layer[" << id << "]: "
1655                         << ec.getLayer()->getName().toLatin1().data() << "\n";
1656         }
1657         else
1658         {
1659                 os << tab << "Layer[" << id << "]: <NULL>\n";
1660         }
1661         //os << ec.layerList << "\n";
1662
1663         os << tab << " Flags[" << id << "]: "
1664                 << (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1665         os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1666         os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1667         os << "\n";
1668
1669         os << tab << "Entities[" << id << "]: \n";
1670
1671 QString s;
1672 os << "(# of entities in this = " << ec.entities.size() << ")\n";
1673 for(int i=0; i<ec.entities.size(); i++)
1674 {
1675         Entity * t = ec.entities[i];
1676         s.sprintf("(Entity = $%08X, rtti = %d\n", t, t->rtti());
1677         os << s.toAscii().data();
1678 }
1679 s.sprintf("(firstEntity = $%08X)\n", ec.firstEntity());
1680 os << s.toAscii().data();
1681
1682         for(Entity * t=ec.firstEntity(); t!=NULL; t=ec.nextEntity())
1683         {
1684                 switch (t->rtti())
1685                 {
1686                 case RS2::EntityInsert:
1687                         os << tab << *((Insert *)t);
1688                         os << tab << *((Entity *)t);
1689                         os << tab << *((EntityContainer *)t);
1690                         break;
1691                 default:
1692                         if (t->isContainer())
1693                                 os << tab << *((EntityContainer *)t);
1694                         else
1695                                 os << tab << *t;
1696
1697                         break;
1698                 }
1699         }
1700
1701         os << tab << "\n\n";
1702         indent--;
1703
1704         delete[] tab;
1705         return os;
1706 }