branchobj.cpp
author insilmaril
Mon, 08 Mar 2010 12:21:46 +0000
changeset 827 a591443f229c
parent 823 0bba81dde1bc
child 835 31841b366d5e
permissions -rw-r--r--
Added missing flag for Bugzilla
     1 #include "branchobj.h"
     2 
     3 #include "attributeitem.h"
     4 #include "branchitem.h"
     5 #include "geometry.h"
     6 #include "mapeditor.h"
     7 #include "mainwindow.h"   
     8 #include "misc.h"
     9 
    10 extern FlagRow *standardFlagsMaster;
    11 extern FlagRow *systemFlagsMaster;
    12 
    13 /////////////////////////////////////////////////////////////////
    14 // BranchObj
    15 /////////////////////////////////////////////////////////////////
    16 
    17 BranchObj::BranchObj (QGraphicsScene* s,TreeItem *ti):OrnamentedObj (s)
    18 {
    19 //    cout << "Const BranchObj (s)  \n";
    20     scene=s;
    21 	treeItem=ti;
    22 	BranchItem *pi=(BranchItem*)(ti->parent());
    23 	if (pi && pi!=ti->getModel()->getRootItem() )
    24 		parObj=pi->getLMO();
    25 	else
    26 		parObj=NULL;
    27 	init();
    28 }
    29 
    30 BranchObj::~BranchObj ()
    31 {
    32 //	cout << "Destr BranchObj of "<<this<<" ("<<treeItem->getHeading().toStdString()<<")"<<endl;
    33 
    34 	// If I'm animated, I need to un-animate myself first
    35 	if (anim.isAnimated() )
    36 	{
    37 		anim.setAnimated (false);
    38 		VymModel *model=treeItem->getModel();
    39 		model->stopAnimation (this);
    40 	}
    41 
    42 	clear();
    43 }
    44 
    45 void BranchObj::init () 
    46 {
    47 	if (parObj)
    48 	{
    49 		absPos=getRandPos();
    50 		absPos+=parObj->getChildPos();
    51 	}
    52 }
    53 
    54 void BranchObj::copy (BranchObj* other)
    55 {
    56     OrnamentedObj::copy(other);
    57 
    58 	setVisibility (other->visible);
    59 
    60     positionBBox();
    61 }
    62 
    63 void BranchObj::clear() 
    64 {
    65 	//setVisibility (true); //FIXME-4 needed?
    66 
    67 	while (!xlink.isEmpty())
    68 		delete xlink.takeFirst();
    69 }
    70 
    71 void BranchObj::setParObjTmp(LinkableMapObj* dst, QPointF m, int off)	
    72 {
    73 	// Temporary link to dst
    74 	// m is position of mouse pointer 
    75 	// offset 0: default 1: below dst   -1 above dst  (if possible)
    76 
    77 	BranchItem *dsti=(BranchItem*)(dst->getTreeItem());
    78 
    79 	BranchItem *pi=(BranchItem*)(dsti->parent());
    80 	int pi_depth=pi->depth();
    81 	BranchObj* bodst=(BranchObj*)dst;
    82 
    83 	if (!tmpParent) 
    84 	{
    85 		tmpParent=true;
    86 		parObjTmpBuf=parObj;
    87 	}
    88 
    89 	if (pi_depth<2) off=0;
    90 	if (off==0)
    91 		link2ParPos=false;
    92 	else
    93 		link2ParPos=true;
    94 	parObj=bodst;
    95 
    96 	setLinkStyle (dst->getDefLinkStyle (dsti));
    97  
    98 	// Move temporary to new position at destination
    99 	// Usually the positioning would be done by reposition(),
   100 	// but then also the destination branch would "Jump" around...
   101 	// Better just do it approximately
   102 	if (dsti->depth()==0)	
   103 	{	// new parent is a mapcenter
   104 		Vector v= ( m - bodst->getChildPos());
   105 		if (v.x()<0) v.setX( v.x()-bbox.width() );
   106 		v.normalize();
   107 		v.scale (100);
   108 		move2RelPos (v.toQPointF());
   109 	} else
   110 	{	
   111 		qreal y;
   112 		if (off==0)
   113 		{
   114 			// new parent is just a branch, link to it
   115 			QRectF t=bodst->getBBoxSizeWithChildren();
   116 			if (dsti->getLastBranch())
   117 				y=t.y() + t.height() ;
   118 			else
   119 				y=t.y();
   120 
   121 			y=t.bottom();
   122 
   123 		} else
   124 		{
   125 			if (off<0)
   126 				// we want to link above dst
   127 				y=bodst->y() - height() + 5;
   128 			else	
   129 				// we want to link below dst
   130 				// Bottom of sel should be 5 pixels above
   131 				// the bottom of the branch _below_ the target:
   132 				// Don't try to find that branch, guess 12 pixels
   133 				y=bodst->getChildPos().y()  -height() + 12; 
   134 		}	
   135 		if (bodst->getOrientation()==LinkableMapObj::LeftOfCenter)
   136 			move ( bodst->getChildPos().x() - linkwidth, y );
   137 		else	
   138 			move (bodst->getChildPos().x() + linkwidth, y );
   139 	}	
   140 
   141 	// updateLinkGeometry is called implicitly in move
   142 	requestReposition();	
   143 }
   144 
   145 void BranchObj::unsetParObjTmp()
   146 {
   147 	if (tmpParent) 
   148 	{
   149 		tmpParent=false;
   150 		link2ParPos=false;
   151 		parObj=parObjTmpBuf;
   152 		parObjTmpBuf=NULL;
   153 		setLinkStyle (getDefLinkStyle(treeItem->parent() ) );
   154 		updateLinkGeometry();
   155 	}		
   156 }
   157 
   158 void BranchObj::setVisibility(bool v, int toDepth)
   159 {
   160 	BranchItem *bi=(BranchItem*)treeItem;
   161     if (bi->depth() <= toDepth)
   162     {
   163 		frame->setVisibility(v);
   164 		heading->setVisibility(v);
   165 		systemFlags->setVisibility(v);
   166 		standardFlags->setVisibility(v);
   167 		LinkableMapObj::setVisibility (v);
   168 		int i;
   169 		for (i=0; i<treeItem->imageCount(); ++i)
   170 			treeItem->getImageObjNum(i)->setVisibility (v);
   171 		for (i=0; i<treeItem->xlinkCount(); ++i)	
   172 			treeItem->getXLinkObjNum(i)->setVisibility ();	
   173 
   174 		// Only change children, if I am not scrolled
   175 		if (! bi->isScrolled() && (bi->depth() < toDepth))
   176 		{
   177 			// Now go recursivly through all children //FIXME-3 are there multiple calls for lower level items???
   178 			for (i=0; i<treeItem->branchCount(); ++i)
   179 				treeItem->getBranchObjNum(i)->setVisibility (v,toDepth);	
   180 		}
   181     } // depth <= toDepth	
   182 	requestReposition();
   183 }	
   184 
   185 void BranchObj::setVisibility(bool v)
   186 {
   187     setVisibility (v,MAX_DEPTH);
   188 }
   189 
   190 
   191 void BranchObj::setLinkColor ()
   192 {
   193 	// Overloaded from LinkableMapObj
   194 	// BranchObj can use color of heading
   195 
   196 	VymModel *model=treeItem->getModel();
   197 	if (model)
   198 	{
   199 		if (model->getMapLinkColorHint()==HeadingColor)
   200 			LinkableMapObj::setLinkColor (heading->getColor() );
   201 		else	
   202 			LinkableMapObj::setLinkColor ();
   203 	}		
   204 }
   205 
   206 void BranchObj::updateContentSize()
   207 {
   208 	calcBBoxSize();
   209 	positionBBox();
   210 	requestReposition();
   211 }
   212 
   213 void BranchObj::positionContents()
   214 {
   215 	for (int i=0; i<treeItem->imageCount(); ++i)
   216 		treeItem->getImageObjNum(i)->reposition();
   217 	OrnamentedObj::positionContents();
   218 }
   219 
   220 void BranchObj::move (double x, double y)
   221 {
   222 	OrnamentedObj::move (x,y);
   223     positionBBox();
   224 }
   225 
   226 void BranchObj::move (QPointF p)
   227 {
   228 	move (p.x(), p.y());
   229 }
   230 
   231 void BranchObj::moveBy (double x, double y)
   232 {
   233 	OrnamentedObj::moveBy (x,y);
   234 	for (int i=0; i<treeItem->branchCount(); ++i)
   235 		treeItem->getBranchObjNum(i)->moveBy (x,y);
   236     positionBBox();
   237 }
   238 	
   239 void BranchObj::moveBy (QPointF p)
   240 {
   241 	moveBy (p.x(), p.y());
   242 }
   243 
   244 
   245 void BranchObj::positionBBox()
   246 {
   247 	QPointF ap=getAbsPos();
   248 	bbox.moveTopLeft (ap);
   249 	positionContents();
   250 
   251 	// set the frame
   252 	frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
   253 
   254 	//Update links to other branches
   255 	XLinkObj *xlo;
   256 	for (int i=0; i<treeItem->xlinkCount(); ++i)	
   257 	{
   258 		xlo=treeItem->getXLinkObjNum(i);
   259 		if (xlo) xlo->updateXLink();
   260 	}	
   261 }
   262 
   263 void BranchObj::calcBBoxSize()
   264 {
   265     QSizeF heading_r=heading->getSize();
   266     qreal heading_w=(qreal) heading_r.width() ;
   267     qreal heading_h=(qreal) heading_r.height() ;
   268     QSizeF sysflags_r=systemFlags->getSize();
   269 	qreal sysflags_h=sysflags_r.height();
   270 	qreal sysflags_w=sysflags_r.width();
   271     QSizeF stanflags_r=standardFlags->getSize();
   272 	qreal stanflags_h=stanflags_r.height();
   273 	qreal stanflags_w=stanflags_r.width();
   274     qreal w;
   275     qreal h;
   276 
   277 	// set width to sum of all widths
   278 	w=heading_w + sysflags_w + stanflags_w;
   279 	// set height to maximum needed height
   280 	h=max (sysflags_h,stanflags_h);
   281 	h=max (h,heading_h);
   282 
   283 	// Save the dimension of flags and heading
   284 	ornamentsBBox.setSize ( QSizeF(w,h));
   285 
   286 	// clickBox includes Flags and Heading
   287     clickBox.setSize (ornamentsBBox.size() );
   288 
   289 	// Floatimages 
   290 	QPointF rp;
   291 
   292 	topPad=botPad=leftPad=rightPad=0;
   293 	bool incV=((BranchItem*)treeItem)->getIncludeImagesVer();
   294 	bool incH=((BranchItem*)treeItem)->getIncludeImagesHor();
   295 	if (incH || incV)
   296 	{
   297 		FloatImageObj *fio;
   298 		for (int i=0; i<treeItem->imageCount(); ++i )	
   299 		{
   300 			fio=treeItem->getImageObjNum(i);
   301 			rp=fio->getRelPos();
   302 			if (incV)
   303 			{
   304 				if (rp.y() < 0) 
   305 					topPad=max (topPad,-rp.y()-h);
   306 				if (rp.y()+fio->height() > 0)
   307 					botPad=max (botPad,rp.y()+fio->height());
   308 			}		
   309 			if (incH)
   310 			{
   311 				if (orientation==LinkableMapObj::RightOfCenter)
   312 				{
   313 					if (-rp.x()-w > 0) 
   314 						leftPad=max (leftPad,-rp.x()-w);
   315 					if (rp.x()+fio->width() > 0)
   316 						rightPad=max (rightPad,rp.x()+fio->width());
   317 				} else
   318 				{
   319 					if (rp.x()< 0) 
   320 						leftPad=max (leftPad,-rp.x());
   321 					if (rp.x()+fio->width() > w)
   322 						rightPad=max (rightPad,rp.x()+fio->width()-w);
   323 				}
   324 			}		
   325 		}	
   326 		h+=topPad+botPad;
   327 		w+=leftPad+rightPad;
   328 	}
   329 
   330 	// Frame thickness
   331     w+=frame->getPadding();
   332     h+=frame->getPadding();
   333 	
   334 	// Finally set size
   335     bbox.setSize (QSizeF (w,h));
   336 }
   337 
   338 void BranchObj::setDockPos()
   339 {
   340 	if (treeItem->getType()==TreeItem::MapCenter)
   341 	{
   342 		// set childPos to middle of MapCenterObj
   343 		childPos.setX( clickBox.topLeft().x() + clickBox.width()/2 );
   344 		childPos.setY( clickBox.topLeft().y() + clickBox.height()/2 );
   345 		parPos=childPos;		
   346 		for (int i=0; i<treeItem->branchCount(); ++i)
   347 			treeItem->getBranchObjNum(i)->updateLinkGeometry();
   348 
   349 	} else
   350 	{
   351 		// Sets childpos and parpos depending on orientation
   352 		if (getOrientation()==LinkableMapObj::LeftOfCenter )
   353 		{
   354 			childPos=QPointF (
   355 				ornamentsBBox.bottomLeft().x(), 
   356 				bottomlineY);
   357 			parPos=QPointF (
   358 				ornamentsBBox.bottomRight().x(),
   359 				bottomlineY);
   360 		} else
   361 		{
   362 			childPos=QPointF (
   363 				ornamentsBBox.bottomRight().x(), 
   364 				bottomlineY);
   365 			parPos=QPointF (
   366 				ornamentsBBox.bottomLeft().x(),
   367 				bottomlineY);
   368 		}
   369 	}
   370 }
   371 
   372 void BranchObj::updateData()
   373 {
   374 	bool changed=false;
   375 	if (!treeItem)
   376 	{
   377 		qWarning ("BranchObj::udpateHeading treeItem==NULL");
   378 		return;
   379 	}
   380 	QString s=treeItem->getHeading();
   381 	if (s!=heading->text())
   382 	{
   383 		heading->setText (s);
   384 		changed=true;
   385 	}
   386 	QStringList TIactiveFlags=treeItem->activeStandardFlagNames();
   387 
   388 	// Add missing standard flags active in TreeItem
   389 	for (int i=0;i<=TIactiveFlags.size()-1;i++)
   390 	{	
   391 		if (!standardFlags->isActive (TIactiveFlags.at(i) ))
   392 		{
   393 			Flag *f=standardFlagsMaster->getFlag(TIactiveFlags.at(i));
   394 			if (f) standardFlags->activate (f);
   395 			changed=true;
   396 		}
   397 	}
   398 	// Remove standard flags no longer active in TreeItem
   399 	QStringList BOactiveFlags=standardFlags->activeFlagNames();
   400 	for (int i=0;i<BOactiveFlags.size();++i)
   401 		if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
   402 		{
   403 			standardFlags->deactivate (BOactiveFlags.at(i));
   404 			changed=true;
   405 		}	
   406 
   407 	// Add missing system flags active in TreeItem
   408 	TIactiveFlags=treeItem->activeSystemFlagNames();
   409 	for (int i=0;i<TIactiveFlags.size();++i)
   410 	{	
   411 		if (!systemFlags->isActive (TIactiveFlags.at(i) ))
   412 		{
   413 			Flag *f=systemFlagsMaster->getFlag(TIactiveFlags.at(i));
   414 			if (f) systemFlags->activate (f);
   415 			changed=true;
   416 		}
   417 	}
   418 	// Remove system flags no longer active in TreeItem
   419 	BOactiveFlags=systemFlags->activeFlagNames();
   420 	for (int i=0;i<BOactiveFlags.size();++i)
   421 	{
   422 		if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
   423 		{
   424 			systemFlags->deactivate (BOactiveFlags.at(i));
   425 			changed=true;
   426 		}	
   427 	}
   428 	if (changed) updateContentSize(); 
   429 }
   430 
   431 void BranchObj::setDefAttr (BranchModification mod, bool keepFrame)
   432 {
   433 	int fontsize;
   434 	switch (treeItem->depth())
   435 	{
   436 		case 0: 
   437 			fontsize=16; 
   438 			break;
   439 		case 1: 
   440 			fontsize=14; 
   441 			break;
   442 		case 2: 
   443 			fontsize=12; 
   444 			break;
   445 		default: 
   446 			fontsize=10; 
   447 			break;
   448 	}	
   449 	setLinkStyle(getDefLinkStyle(treeItem->parent() ));
   450 	setLinkColor ();
   451 	QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
   452 	font.setPointSize(fontsize);
   453 	heading->setFont(font );
   454 
   455 	if (mod==NewBranch && !keepFrame)
   456 	{
   457 		if (treeItem->depth()==0)
   458 			setFrameType (FrameObj::Rectangle);
   459 		else	
   460 			setFrameType (FrameObj::NoFrame);
   461 	}
   462 	if (mod==NewBranch)
   463 		setColor (treeItem->getHeadingColor() );
   464 	else
   465 	{
   466 		// Also set styles for children
   467 		for (int i=0; i<treeItem->branchCount(); ++i)
   468 			treeItem->getBranchObjNum(i)->setDefAttr(MovedBranch);
   469 	}		
   470 	calcBBoxSize();
   471 }
   472 
   473 void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
   474 {
   475 	qreal th = bboxTotal.height();	
   476 	int depth=0;
   477 	if (parObj)	depth=1 + parObj->getTreeItem()->depth();
   478 // TODO testing
   479 /*
   480 	QString h=QString (depth+1,' ');
   481 	h+=treeItem->getHeading();
   482 	h+=QString (15,' ');
   483 	h.truncate (15);
   484 	QPointF pp; 
   485 	if (parObj) pp=parObj->getChildPos();
   486 	cout << "BO::alignRelTo ";
   487 	cout<<h.toStdString();
   488 	cout << "    d="<<depth;
   489 	cout <<"  parO="<<parObj;
   490 //cout<<  "  ref="<<ref<<
   491 //cout <<	"  bbox.tL="<<bboxTotal.topLeft();
   492 cout<<	"  absPos="<<absPos<<
   493 		"  relPos="<<relPos<<
   494 //		"  parPos="<<pp<<
   495 //		"  w="<<bbox.width()<<
   496 //		"  h="<<bbox.height()<<
   497 //		"  orient="<<orientation<<
   498 //		"  alignSelf="<<alignSelf<<
   499 //		"  scrolled="<<((BranchItem*)treeItem)->isScrolled()<<
   500 //		"  pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
   501 //		"  hidden="<<hidden<<
   502 //		"  th="<<th<<
   503 		endl;
   504 */
   505 
   506 	setOrientation();
   507 	//updateLinkGeometry();
   508 
   509 	if (depth==1)
   510 	{
   511 		move2RelPos (getRelPos() );
   512 	}
   513 	if (depth>1)
   514     {
   515 		// Align myself depending on orientation and parent, but
   516 		// only if I am not a mainbranch or mapcenter itself
   517 
   518 		if (anim.isAnimated())
   519 		{
   520 			move2RelPos(anim);
   521 		} else
   522 		{
   523 			LinkableMapObj::Orientation o;
   524 			o=parObj->getOrientation();
   525 			if (alignSelf)
   526 				switch (orientation) 
   527 				{
   528 					case LinkableMapObj::LeftOfCenter:
   529 						move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
   530 						//move (ref.x() , ref.y() + (th-bbox.height())/2 );
   531 					break;
   532 					case LinkableMapObj::RightOfCenter:	
   533 						move (ref.x() , ref.y() + (th-bbox.height())/2  );
   534 					break;
   535 					default:
   536 						qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
   537 					break;
   538 			}
   539 		}
   540     }		
   541 
   542 	if ( ((BranchItem*)treeItem)->isScrolled() ) return;
   543 
   544     // Set reference point for alignment of children
   545     QPointF ref2;
   546     if (orientation==LinkableMapObj::LeftOfCenter)
   547 		ref2.setX(bbox.topLeft().x() - linkwidth);
   548     else	
   549 		ref2.setX(bbox.topRight().x() + linkwidth);
   550 
   551 	if (depth==1)
   552 		ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
   553 	else	
   554 		ref2.setY(ref.y() );	
   555 
   556     // Align the attribute children depending on reference point 
   557 	// on top like in TreeEditor
   558 	for (int i=0; i<treeItem->attributeCount(); ++i)
   559     {	
   560 		if (!treeItem->getAttributeNum(i)->isHidden())
   561 		{
   562 			BranchObj *bo=(BranchObj*)(treeItem->getAttributeNum(i)->getBranchObj());
   563 			if (!bo) break;
   564 			bo->alignRelativeTo (ref2,true);
   565 
   566 			// append next branch below current one
   567 			ref2.setY(ref2.y() + bo->getBBoxSizeWithChildren().height() );
   568 		}
   569     }
   570     // Align the branch children depending on reference point 
   571 	for (int i=0; i<treeItem->branchCount(); ++i)
   572     {	
   573 		if (!treeItem->getBranchNum(i)->isHidden())
   574 		{
   575 			treeItem->getBranchObjNum(i)->alignRelativeTo (ref2,true);
   576 
   577 			// append next branch below current one
   578 			ref2.setY(ref2.y() + treeItem->getBranchObjNum(i)->getBBoxSizeWithChildren().height() );
   579 		}
   580     }
   581 }
   582 
   583 
   584 void BranchObj::reposition()
   585 {	
   586 /* TODO testing only
   587 	if (!treeItem->getHeading().isEmpty())
   588 		cout << "BO::reposition  "<<qPrintable(treeItem->getHeading())<<endl;
   589 	else	
   590 		cout << "BO::reposition  ???"<<endl;
   591 //	cout << "  orient="<<orientation<<endl;
   592 */		
   593 
   594 	if (treeItem->depth()==0)
   595 	{
   596 		// only calculate the sizes once. If the deepest LMO 
   597 		// changes its height,
   598 		// all upper LMOs have to change, too.
   599 		calcBBoxSizeWithChildren();
   600 		updateLinkGeometry();	// This update is needed if the scene is resized 
   601 						// due to excessive moving of a FIO
   602 
   603 	    alignRelativeTo ( QPointF (absPos.x(),
   604 			absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   605 		positionBBox();	// Reposition bbox and contents
   606 	} else
   607 	{
   608 		// This is only important for moving branches:
   609 		// For editing a branch it isn't called...
   610 	    alignRelativeTo ( QPointF (absPos.x(),
   611 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   612 	}
   613 }
   614 
   615 void BranchObj::unsetAllRepositionRequests()
   616 {
   617 	repositionRequest=false;
   618 	for (int i=0; i<treeItem->branchCount(); ++i)
   619 		treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
   620 }
   621 
   622 QRectF BranchObj::getBBoxSizeWithChildren()
   623 {
   624 	return bboxTotal;
   625 }
   626 
   627 ConvexPolygon BranchObj::getBoundingPolygon()	
   628 {
   629 /*
   630 	if (!pi)	//FIXME-3 Testing only
   631 	{
   632 		pi=scene->addPolygon(MapObj::getBoundingPolygon() );
   633 		pi->setPen(Qt::NoPen);
   634 		pi->setBrush( QColor(qrand()%32*8,qrand()%32*8,qrand()%32*8) );
   635 		pi->setZValue(Z_BBOX);
   636 	}
   637 	*/
   638 
   639 	if (treeItem->branchCount()==0 || treeItem->depth()==0)
   640 	{
   641 		if (pi) pi->setPolygon (MapObj::getBoundingPolygon() );
   642 		return MapObj::getBoundingPolygon();
   643 	}
   644 
   645 	calcBBoxSizeWithChildren();	//FIXME-3 really needed?
   646 	QPolygonF p;
   647 	p<<bboxTotal.topLeft();
   648 	p<<bboxTotal.topRight();
   649 	p<<bboxTotal.bottomRight();
   650 	p<<bboxTotal.bottomLeft();
   651 	//cout << "BO::getBP (total)  "<<treeItem->getHeadingStd()<<"  tL="<<bboxTotal.topLeft()<<"  bR="<<bboxTotal.bottomRight()<<endl;
   652 	//cout << "                   "<<"  tL="<<bbox.topLeft()<<"  bR="<<bbox.bottomRight()<<endl;
   653 	if (pi) pi->setPolygon (p );
   654 	return p;
   655 }
   656 
   657 void BranchObj::calcBBoxSizeWithChildren()
   658 {	
   659 	// This is initially called only from reposition and
   660 	// and only for mapcenter. So it won't be
   661 	// called more than once for a single user 
   662 	// action
   663 	
   664 
   665 	// Calculate size of LMO including all children (to align them later)
   666 	bboxTotal.setX(bbox.x() );
   667 	bboxTotal.setY(bbox.y() );
   668 
   669 	// if branch is scrolled, ignore children, but still consider floatimages
   670 	BranchItem *bi=(BranchItem*)treeItem;
   671 	if ( bi->isScrolled() ) 
   672 	{
   673 		bboxTotal.setWidth (bbox.width());
   674 		bboxTotal.setHeight(bbox.height());
   675 		return;
   676 	}
   677 	
   678 	if (bi->isHidden())
   679 	{
   680 		bboxTotal.setWidth (0);
   681 		bboxTotal.setHeight(0);
   682 		if (parObj)
   683 		{
   684 			bboxTotal.setX (parObj->x());
   685 			bboxTotal.setY (parObj->y());
   686 		} else
   687 		{
   688 			bboxTotal.setX (bbox.x());
   689 			bboxTotal.setY (bbox.y());
   690 		}
   691 		return;
   692 	}
   693 	
   694 	QRectF r(0,0,0,0);
   695 	QRectF br;
   696 	// Now calculate recursivly
   697 	// sum of heights 
   698 	// maximum of widths 
   699 	// minimum of y
   700 	for (int i=0; i<treeItem->branchCount(); i++)
   701 	{
   702 		if (!bi->getBranchNum(i)->isHidden())
   703 		{
   704 			BranchObj *bo=bi->getBranchObjNum(i);
   705 			bo->calcBBoxSizeWithChildren();
   706 			br=bo->getBBoxSizeWithChildren();
   707 			r.setWidth( max (br.width(), r.width() ));
   708 			r.setHeight(br.height() + r.height() );
   709 			if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
   710 			if (br.x()<bboxTotal.x()) bboxTotal.setX(br.x());
   711 		}
   712 	}
   713 	for (int i=0; i<treeItem->attributeCount(); i++)
   714 	{
   715 		if (!bi->getAttributeNum(i)->isHidden())
   716 		{
   717 			BranchObj *bo=bi->getAttributeNum(i)->getBranchObj();
   718 			bo->calcBBoxSizeWithChildren();
   719 			br=bo->getBBoxSizeWithChildren();
   720 			r.setWidth( max (br.width(), r.width() ));
   721 			r.setHeight(br.height() + r.height() );
   722 			if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
   723 			if (br.x()<bboxTotal.x()) bboxTotal.setX(br.x());
   724 		}
   725 	}
   726 	// Add myself and also
   727 	// add width of link to sum if necessary
   728 	if (bi->branchCount()<1)
   729 		bboxTotal.setWidth (bbox.width() + r.width() );
   730 	else	
   731 		bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
   732 	
   733 	bboxTotal.setHeight(max (r.height(),  bbox.height()));
   734 }
   735 
   736 void BranchObj::setAnimation(const AnimPoint &ap)
   737 {
   738 	anim=ap;
   739 }
   740 
   741 bool BranchObj::animate()
   742 {
   743 	anim.animate ();
   744 	if ( anim.isAnimated() )
   745 	{
   746 		setRelPos (anim);
   747 		return true;
   748 	}
   749 	parObj->reposition();	// we might have been relinked meanwhile
   750 	return false;
   751 }
   752