branchobj.cpp
author insilmaril
Tue, 18 Aug 2009 12:39:07 +0000
changeset 788 78ba80b54bc4
parent 786 6269016c9905
child 789 d85834ad8c54
permissions -rw-r--r--
Fix for segfault when deleting MCO (invalid QModelIndex needs to be returned in index(TreeItem*) )
     1 #include "branchobj.h"
     2 
     3 #include "branchitem.h"
     4 #include "geometry.h"
     5 #include "mapeditor.h"
     6 #include "mainwindow.h"
     7 #include "misc.h"
     8 
     9 extern FlagRow *standardFlagsMaster;
    10 extern FlagRow *systemFlagsMaster;
    11 
    12 /////////////////////////////////////////////////////////////////
    13 // BranchObj
    14 /////////////////////////////////////////////////////////////////
    15 
    16 BranchObj::BranchObj () :OrnamentedObj()	// FIXME-3 needed at all?
    17 {
    18 //    cout << "Const BranchObj ()\n";
    19     setParObj (this);	
    20     init();
    21 }
    22 
    23 BranchObj::BranchObj (QGraphicsScene* s):OrnamentedObj (s)// FIXME-3 needed at all?
    24 {
    25 //    cout << "Const BranchObj (s)  \n";
    26 	parObj=NULL;
    27     scene=s;
    28 	init();
    29 }
    30 
    31 BranchObj::BranchObj (QGraphicsScene* s, LinkableMapObj* p):OrnamentedObj (s)// FIXME-3 needed at all?
    32 {
    33 //    cout << "Const BranchObj (s,p)\n";
    34     scene=s;
    35     setParObj (p);	
    36 	if (treeItem->depth()==1)	// FIXME-3 needed to recursively calc depth?
    37 		// Calc angle to mapCenter if I am a mainbranch
    38 		// needed for reordering the mainbranches clockwise 
    39 		// around mapcenter 
    40 		angle=getAngle (QPointF (x() - parObj->getChildPos().x() , 
    41 								(y() - parObj->getChildPos().y() ) ) );
    42     init();
    43 }
    44 
    45 BranchObj::~BranchObj ()
    46 {
    47 //	cout << "Destr BranchObj of "<<this<<" ("<<treeItem->getHeading().toStdString()<<")"<<endl;
    48 
    49 	// If I'm animated, I need to un-animate myself first
    50 	if (anim.isAnimated() )
    51 	{
    52 		anim.setAnimated (false);
    53 		VymModel *model=treeItem->getModel();
    54 		model->stopAnimation (this);
    55 	}
    56 
    57 	// Check, if this branch was the last child to be deleted
    58 	// If so, unset the scrolled flags in parent // FIXME-2 better do this in model?
    59 
    60 	/*
    61 	BranchObj *po=(BranchObj*)parObj;
    62 	BranchObj *bo;
    63 	if (po)
    64 	{
    65 		bo=((BranchObj*)parObj)->getLastBranch();
    66 		if (bo) po->unScroll();
    67 	}
    68 	*/
    69 	clear();
    70 }
    71 
    72 bool BranchObj::operator< ( const BranchObj & other )
    73 {
    74     return  angle < other.angle;
    75 }
    76 
    77 bool BranchObj::operator== ( const BranchObj & other )
    78 {
    79     return angle == other.angle;
    80 }
    81 
    82 void BranchObj::init () 
    83 {
    84 	if (parObj)
    85 	{
    86 		absPos=getRandPos();
    87 		absPos+=parObj->getChildPos();
    88 	}
    89 }
    90 
    91 void BranchObj::copy (BranchObj* other)
    92 {
    93     OrnamentedObj::copy(other);
    94 
    95 	setVisibility (other->visible);
    96 
    97 	angle=other->angle;
    98 
    99     positionBBox();
   100 }
   101 
   102 void BranchObj::clear() 
   103 {
   104 	//setVisibility (true); //FIXME-4 needed?
   105 
   106 	while (!xlink.isEmpty())
   107 		delete xlink.takeFirst();
   108 }
   109 
   110 bool isAbove (BranchObj* a, BranchObj *b)
   111 {
   112 	if (a->angle < b->angle)
   113 		return true;
   114 	else	
   115 		return false;
   116 }
   117 
   118 void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPointF m, int off)
   119 {
   120 	// Temporary link to lmo
   121 	// m is position of mouse pointer 
   122 	// offset 0: default 1: below lmo   -1 above lmo  (if possible)
   123 
   124 	BranchItem *pi=(BranchItem*)(lmo->getTreeItem()->parent());
   125 	int pi_depth=pi->depth();
   126 	BranchObj* o=(BranchObj*)(lmo);
   127 	if (!parObjTmpBuf) 
   128 		parObjTmpBuf=parObj;
   129 
   130 	// ignore mapcenter and mainbranch	//FIXME-3 MCO meanwhile also could be relinked
   131 	if (pi_depth<2) off=0;
   132 	if (off==0)
   133 		link2ParPos=false;
   134 	else
   135 		link2ParPos=true;
   136 	parObj=o;
   137 
   138 	// setLinkStyle calls updateLinkGeometry, only set it once
   139 	//LinkableMapObj::Style ls=getDefLinkStyle (lmo->getTreeItem() );
   140 	//if (style!=ls ) setLinkStyle (ls);
   141 	setLinkStyle (lmo->getDefLinkStyle (lmo->getTreeItem()));
   142 
   143 	// Move temporary to new position at destination
   144 	// Usually the positioning would be done by reposition(),
   145 	// but then also the destination branch would "Jump" around...
   146 	// Better just do it approximately
   147 	if (parObj->getTreeItem()->depth()==0)	
   148 	{	// new parent is a mapcenter
   149 
   150 		QPointF p= normalise ( QPointF (m.x() - o->getChildPos().x(),
   151 									  m.y() - o->getChildPos().y() ));
   152 		if (p.x()<0) p.setX( p.x()-bbox.width() );
   153 		move2RelPos (p);
   154 	} else
   155 	{	
   156 		qreal y;
   157 		if (off==0)
   158 		{
   159 			// new parent is just a branch, link to it
   160 			QRectF t=o->getBBoxSizeWithChildren();
   161 			if (o->getTreeItem()->getLastBranch())
   162 				y=t.y() + t.height() ;
   163 			else
   164 				y=t.y();
   165 
   166 		} else
   167 		{
   168 			if (off<0)
   169 				// we want to link above lmo
   170 				y=o->y() - height() + 5;
   171 			else	
   172 				// we want to link below lmo
   173 				// Bottom of sel should be 5 pixels above
   174 				// the bottom of the branch _below_ the target:
   175 				// Don't try to find that branch, guess 12 pixels
   176 				y=o->getChildPos().y()  -height() + 12; 
   177 		}	
   178 		if (o->getOrientation()==LinkableMapObj::LeftOfCenter)
   179 			move ( o->getChildPos().x() - linkwidth, y );
   180 		else	
   181 			move (o->getChildPos().x() + linkwidth, y );
   182 	}	
   183 
   184 	// updateLinkGeometry is called implicitly in move
   185 	requestReposition();	
   186 }
   187 
   188 void BranchObj::unsetParObjTmp()
   189 {
   190 	if (parObjTmpBuf) 
   191 	{
   192 		link2ParPos=false;
   193 		parObj=parObjTmpBuf;
   194 		parObjTmpBuf=NULL;
   195 		setLinkStyle (getDefLinkStyle(treeItem->parent() ) );
   196 		updateLinkGeometry();
   197 	}		
   198 }
   199 
   200 void BranchObj::setVisibility(bool v, int toDepth)
   201 {
   202 	BranchItem *bi=(BranchItem*)treeItem;
   203     if (bi->depth() <= toDepth)
   204     {
   205 		frame->setVisibility(v);
   206 		heading->setVisibility(v);
   207 		systemFlags->setVisibility(v);
   208 		standardFlags->setVisibility(v);
   209 		LinkableMapObj::setVisibility (v);
   210 		int i;
   211 		for (i=0; i<treeItem->imageCount(); ++i)
   212 			treeItem->getImageObjNum(i)->setVisibility (v);
   213 		for (i=0; i<xlink.size(); ++i)	
   214 			xlink.at(i)->setVisibility ();	
   215 
   216 		// Only change children, if I am not scrolled
   217 		if (! bi->isScrolled() && (bi->depth() < toDepth))
   218 		{
   219 			// Now go recursivly through all children //FIXME-3 are there multiple calls for lower level items???
   220 			for (i=0; i<treeItem->branchCount(); ++i)
   221 				treeItem->getBranchObjNum(i)->setVisibility (v,toDepth);	
   222 		}
   223     } // depth <= toDepth	
   224 	requestReposition();
   225 }	
   226 
   227 void BranchObj::setVisibility(bool v)
   228 {
   229     setVisibility (v,MAX_DEPTH);
   230 }
   231 
   232 
   233 void BranchObj::setLinkColor ()
   234 {
   235 	// Overloaded from LinkableMapObj
   236 	// BranchObj can use color of heading
   237 
   238 	VymModel *model=treeItem->getModel();
   239 	if (model)
   240 	{
   241 		if (model->getMapLinkColorHint()==HeadingColor)
   242 			LinkableMapObj::setLinkColor (heading->getColor() );
   243 		else	
   244 			LinkableMapObj::setLinkColor ();
   245 	}		
   246 }
   247 
   248 void BranchObj::updateContentSize()
   249 {
   250 	calcBBoxSize();
   251 	positionBBox();
   252 	requestReposition();
   253 }
   254 
   255 void BranchObj::positionContents()
   256 {
   257 	for (int i=0; i<treeItem->imageCount(); ++i)
   258 		treeItem->getImageObjNum(i)->reposition();
   259 	OrnamentedObj::positionContents();
   260 }
   261 
   262 void BranchObj::move (double x, double y)
   263 {
   264 	OrnamentedObj::move (x,y);
   265 	FloatImageObj *fio;
   266     for (int i=0; i<treeItem->imageCount(); ++i )
   267 	{
   268 		fio=treeItem->getImageObjNum(i);
   269 		if (fio) fio->reposition();
   270 	}
   271     positionBBox();
   272 }
   273 
   274 void BranchObj::move (QPointF p)
   275 {
   276 	move (p.x(), p.y());
   277 }
   278 
   279 void BranchObj::moveBy (double x, double y)
   280 {
   281 	OrnamentedObj::moveBy (x,y);
   282 	for (int i=0; i<treeItem->branchCount(); ++i)
   283 		treeItem->getBranchObjNum(i)->moveBy (x,y);
   284     positionBBox();
   285 }
   286 	
   287 void BranchObj::moveBy (QPointF p)
   288 {
   289 	moveBy (p.x(), p.y());
   290 }
   291 
   292 
   293 void BranchObj::positionBBox()
   294 {
   295 	QPointF ap=getAbsPos();
   296 	bbox.moveTopLeft (ap);
   297 	positionContents();
   298 
   299 	// set the frame
   300 	frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
   301 
   302 	// Update links to other branches
   303 	for (int i=0; i<xlink.size(); ++i)
   304 		xlink.at(i)->updateXLink();
   305 }
   306 
   307 void BranchObj::calcBBoxSize()
   308 {
   309     QSizeF heading_r=heading->getSize();
   310     qreal heading_w=(qreal) heading_r.width() ;
   311     qreal heading_h=(qreal) heading_r.height() ;
   312     QSizeF sysflags_r=systemFlags->getSize();
   313 	qreal sysflags_h=sysflags_r.height();
   314 	qreal sysflags_w=sysflags_r.width();
   315     QSizeF stanflags_r=standardFlags->getSize();
   316 	qreal stanflags_h=stanflags_r.height();
   317 	qreal stanflags_w=stanflags_r.width();
   318     qreal w;
   319     qreal h;
   320 
   321 	// set width to sum of all widths
   322 	w=heading_w + sysflags_w + stanflags_w;
   323 	// set height to maximum needed height
   324 	h=max (sysflags_h,stanflags_h);
   325 	h=max (h,heading_h);
   326 
   327 	// Save the dimension of flags and heading
   328 	ornamentsBBox.setSize ( QSizeF(w,h));
   329 
   330 	// clickBox includes Flags and Heading
   331     clickBox.setSize (ornamentsBBox.size() );
   332 
   333 	// Floatimages 
   334 	QPointF rp;
   335 
   336 	topPad=botPad=leftPad=rightPad=0;
   337 	bool incV=((BranchItem*)treeItem)->getIncludeImagesVer();
   338 	bool incH=((BranchItem*)treeItem)->getIncludeImagesHor();
   339 	if (incH || incV)
   340 	{
   341 		FloatImageObj *fio;
   342 		for (int i=0; i<treeItem->imageCount(); ++i )	
   343 		{
   344 			fio=treeItem->getImageObjNum(i);
   345 			rp=fio->getRelPos();
   346 			if (incV)
   347 			{
   348 				if (rp.y() < 0) 
   349 					topPad=max (topPad,-rp.y()-h);
   350 				if (rp.y()+fio->height() > 0)
   351 					botPad=max (botPad,rp.y()+fio->height());
   352 			}		
   353 			if (incH)
   354 			{
   355 				if (orientation==LinkableMapObj::RightOfCenter)
   356 				{
   357 					if (-rp.x()-w > 0) 
   358 						leftPad=max (leftPad,-rp.x()-w);
   359 					if (rp.x()+fio->width() > 0)
   360 						rightPad=max (rightPad,rp.x()+fio->width());
   361 				} else
   362 				{
   363 					if (rp.x()< 0) 
   364 						leftPad=max (leftPad,-rp.x());
   365 					if (rp.x()+fio->width() > w)
   366 						rightPad=max (rightPad,rp.x()+fio->width()-w);
   367 				}
   368 			}		
   369 		}	
   370 		h+=topPad+botPad;
   371 		w+=leftPad+rightPad;
   372 	}
   373 
   374 	// Frame thickness
   375     w+=frame->getPadding();
   376     h+=frame->getPadding();
   377 	
   378 	// Finally set size
   379     bbox.setSize (QSizeF (w,h));
   380 }
   381 
   382 void BranchObj::setDockPos()
   383 {
   384 	if (treeItem->getType()==TreeItem::MapCenter)
   385 	{
   386 		// set childPos to middle of MapCenterObj
   387 		childPos.setX( clickBox.topLeft().x() + clickBox.width()/2 );
   388 		childPos.setY( clickBox.topLeft().y() + clickBox.height()/2 );
   389 		parPos=childPos;		
   390 		for (int i=0; i<treeItem->branchCount(); ++i)
   391 			treeItem->getBranchObjNum(i)->updateLinkGeometry();
   392 
   393 	} else
   394 	{
   395 		// Sets childpos and parpos depending on orientation
   396 		if (getOrientation()==LinkableMapObj::LeftOfCenter )
   397 		{
   398 			childPos=QPointF (
   399 				ornamentsBBox.bottomLeft().x(), 
   400 				bottomlineY);
   401 			parPos=QPointF (
   402 				ornamentsBBox.bottomRight().x(),
   403 				bottomlineY);
   404 		} else
   405 		{
   406 			childPos=QPointF (
   407 				ornamentsBBox.bottomRight().x(), 
   408 				bottomlineY);
   409 			parPos=QPointF (
   410 				ornamentsBBox.bottomLeft().x(),
   411 				bottomlineY);
   412 		}
   413 	}
   414 }
   415 
   416 void BranchObj::updateData()
   417 {
   418 	bool changed=false;
   419 	if (!treeItem)
   420 	{
   421 		qWarning ("BranchObj::udpateHeading treeItem==NULL");
   422 		return;
   423 	}
   424 	QString s=treeItem->getHeading();
   425 	if (s!=heading->text())
   426 	{
   427 		heading->setText (s);
   428 		changed=true;
   429 	}
   430 	QStringList TIactiveFlags=treeItem->activeStandardFlagNames();
   431 
   432 	// Add missing standard flags active in TreeItem
   433 	for (int i=0;i<=TIactiveFlags.size()-1;i++)
   434 	{	
   435 		if (!standardFlags->isActive (TIactiveFlags.at(i) ))
   436 		{
   437 			Flag *f=standardFlagsMaster->getFlag(TIactiveFlags.at(i));
   438 			if (f) standardFlags->activate (f);
   439 			changed=true;
   440 		}
   441 	}
   442 	// Remove standard flags no longer active in TreeItem
   443 	QStringList BOactiveFlags=standardFlags->activeFlagNames();
   444 	for (int i=0;i<BOactiveFlags.size();++i)
   445 		if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
   446 		{
   447 			standardFlags->deactivate (BOactiveFlags.at(i));
   448 			changed=true;
   449 		}	
   450 
   451 	// Add missing system flags active in TreeItem
   452 	TIactiveFlags=treeItem->activeSystemFlagNames();
   453 	for (int i=0;i<TIactiveFlags.size();++i)
   454 	{	
   455 		if (!systemFlags->isActive (TIactiveFlags.at(i) ))
   456 		{
   457 			Flag *f=systemFlagsMaster->getFlag(TIactiveFlags.at(i));
   458 			if (f) systemFlags->activate (f);
   459 			changed=true;
   460 		}
   461 	}
   462 	// Remove system flags no longer active in TreeItem
   463 	BOactiveFlags=systemFlags->activeFlagNames();
   464 	for (int i=0;i<BOactiveFlags.size();++i)
   465 	{
   466 		if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
   467 		{
   468 			systemFlags->deactivate (BOactiveFlags.at(i));
   469 			changed=true;
   470 		}	
   471 	}
   472 	updateContentSize();
   473 }
   474 
   475 
   476 void BranchObj::addXLink (XLinkObj *xlo)
   477 {
   478 	xlink.append (xlo);
   479 	
   480 }
   481 
   482 void BranchObj::removeXLinkRef (XLinkObj *xlo)
   483 {
   484 	xlink.removeAt (xlink.indexOf(xlo));
   485 }
   486 
   487 void BranchObj::deleteXLink(XLinkObj *xlo)
   488 {
   489 	xlo->deactivate();
   490 	if (!xlo->isUsed()) delete (xlo);
   491 }
   492 
   493 void BranchObj::deleteXLinkAt (int i)
   494 {
   495 	XLinkObj *xlo=xlink.at(i);
   496 	xlo->deactivate();
   497 	if (!xlo->isUsed()) delete(xlo);
   498 }
   499 
   500 XLinkObj* BranchObj::XLinkAt (int i)
   501 {
   502 	return xlink.at(i);
   503 }
   504 
   505 BranchObj* BranchObj::XLinkTargetAt (int i)
   506 {
   507 	if (i>=0 && i<xlink.size())
   508 	{
   509 		if (xlink.at(i))
   510 			return xlink.at(i)->otherBranch (this);
   511 	}
   512 	return NULL;
   513 }
   514 
   515  
   516 // FIXME-3 FloatImageObj* BranchObj::addFloatImage ()
   517 /*
   518 {
   519 	FloatImageObj *newfi=new FloatImageObj (scene,this);
   520 	floatimage.append (newfi);
   521 	if ( ((BranchItem*)treeItem)->hasScrolledParent((BranchItem*)treeItem) )
   522 		newfi->setVisibility (false);
   523 	else	
   524 		newfi->setVisibility(visible);
   525 	//calcBBoxSize();
   526 	//positionBBox();
   527 	requestReposition();
   528 	return newfi;
   529 }
   530 */
   531 
   532 //FIXME-3 FloatImageObj* BranchObj::addFloatImage (FloatImageObj *fio)
   533 /*
   534 {
   535 	FloatImageObj *newfi=new FloatImageObj (scene,this);
   536 	floatimage.append (newfi);
   537 	newfi->copy (fio);
   538 	if (((BranchItem*)treeItem)->hasScrolledParent((BranchItem*)treeItem) )
   539 		newfi->setVisibility (false);
   540 	else	
   541 		newfi->setVisibility(visible);
   542 	//calcBBoxSize();
   543 	//positionBBox();
   544 	requestReposition();
   545 	return newfi;
   546 }
   547 */
   548 
   549 /* FIXME-3 FloatImageObj* BranchObj::getFirstFloatImage ()
   550 {
   551     return floatimage.first();
   552 }
   553 
   554 FloatImageObj* BranchObj::getLastFloatImage ()
   555 {
   556     return floatimage.last();
   557 }
   558 
   559 FIXME -3 FloatImageObj* BranchObj::getFloatImageNum (const uint &i)
   560 {
   561     return floatimage.at(i);
   562 }
   563 
   564 void BranchObj::removeFloatImage (FloatImageObj *fio)
   565 {
   566 	int i=floatimage.indexOf (fio);
   567 	if (i>-1) delete (floatimage.takeAt (i));
   568 	calcBBoxSize();
   569 	positionBBox();
   570 	requestReposition();
   571 }
   572 */
   573 
   574 void BranchObj::savePosInAngle ()
   575 {
   576 	// Save position in angle
   577 	for (int i=0; i<treeItem->branchCount(); ++i)
   578 		treeItem->getBranchObjNum(i)->angle=i;
   579 }
   580 
   581 void BranchObj::setDefAttr (BranchModification mod)
   582 {
   583 	int fontsize;
   584 	switch (treeItem->depth())
   585 	{
   586 		case 0: fontsize=16; break;
   587 		case 1: fontsize=12; break;
   588 		default: fontsize=10; break;
   589 	}	
   590 	setLinkStyle(getDefLinkStyle(treeItem->parent() ));
   591 	setLinkColor ();
   592 	QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
   593 	font.setPointSize(fontsize);
   594 	heading->setFont(font );
   595 
   596 	if (mod==NewBranch)
   597 		setColor (treeItem->getHeadingColor() );
   598 	calcBBoxSize();
   599 }
   600 
   601 void BranchObj::sortChildren() //FIXME-3 not moved to model yet 
   602 {
   603 /*
   604 	int childCount=branch.count(); 
   605 	int curChildIndex;
   606 	bool madeChanges=false;
   607 	do
   608 	{
   609 		madeChanges=false;
   610 		for(curChildIndex=1;curChildIndex<childCount;curChildIndex++){
   611 			BranchObj* curChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex);
   612 			BranchObj* prevChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex-1);
   613 			if(prevChild->heading->text().compare(curChild->heading->text())>0)
   614 			{
   615 				this->moveBranchUp(curChild);
   616 				madeChanges=true;
   617 			}
   618 		}
   619 	}while(madeChanges);
   620 */
   621 }
   622 
   623 void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
   624 {
   625 	qreal th = bboxTotal.height();	
   626 	int depth=treeItem->depth();	// FIXME-3 needed to recursively calc depth?
   627 // TODO testing
   628 /*
   629 
   630 	QString h=QString (depth,' ');
   631 	h+=treeItem->getHeading();
   632 	h+=QString (15,' ');
   633 	h.truncate (15);
   634 	QPointF pp; if (parObj) pp=parObj->getChildPos();
   635 	cout << "BO::alignRelTo ";
   636 	cout<<h.toStdString();
   637 	cout << "    d="<<depth<<
   638 //cout<<  "  ref="<<ref<<
   639       	"  bbox.tL="<<bboxTotal.topLeft()<<
   640 		"  absPos="<<absPos<<
   641 //		"  relPos="<<relPos<<
   642 //		"  parPos="<<pp<<
   643 		"  w="<<bbox.width()<<
   644 		"  h="<<bbox.height()<<
   645 //		"  orient="<<orientation<<
   646 //		"  alignSelf="<<alignSelf<<
   647 //		"  scrolled="<<((BranchItem*)treeItem)->isScrolled()<<
   648 //		"  pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
   649 //		"  hidden="<<hidden<<
   650 		"  th="<<th<<
   651 		endl;
   652 */
   653 
   654 	setOrientation();
   655 	//updateLinkGeometry();
   656 
   657 	if (depth==1 && parObj)
   658 	{
   659 		// Position relatively, if needed
   660 		//if (useRelPos) move2RelPos (relPos.x(), relPos.y());
   661 
   662 		// Calc angle to mapCenter if I am a mainbranch
   663 		// needed for reordering the mainbranches clockwise 
   664 		// around mapcenter 
   665 		angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ), 
   666 								(int)(y() - parObj->getChildPos().y() ) ) );
   667 	}							
   668 	if (depth>1)
   669     {
   670 		// Align myself depending on orientation and parent, but
   671 		// only if I am not a mainbranch or mapcenter itself
   672 
   673 		if (anim.isAnimated())
   674 		{
   675 			move2RelPos(anim);
   676 		} else
   677 		{
   678 			LinkableMapObj::Orientation o;
   679 			o=parObj->getOrientation();
   680 			if (alignSelf)
   681 				switch (orientation) 
   682 				{
   683 					case LinkableMapObj::LeftOfCenter:
   684 						move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
   685 						//move (ref.x() , ref.y() + (th-bbox.height())/2 );
   686 					break;
   687 					case LinkableMapObj::RightOfCenter:	
   688 						move (ref.x() , ref.y() + (th-bbox.height())/2  );
   689 					break;
   690 					default:
   691 						qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
   692 					break;
   693 			}
   694 		}
   695     }		
   696 
   697 	if ( ((BranchItem*)treeItem)->isScrolled() ) return;
   698 
   699     // Set reference point for alignment of children
   700     QPointF ref2;
   701     if (orientation==LinkableMapObj::LeftOfCenter)
   702 		ref2.setX(bbox.topLeft().x() - linkwidth);
   703     else	
   704 		ref2.setX(bbox.topRight().x() + linkwidth);
   705 
   706 	if (depth==1)
   707 		ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
   708 	else	
   709 		ref2.setY(ref.y() );	
   710 
   711     // Align the children depending on reference point 
   712 	for (int i=0; i<treeItem->branchCount(); ++i)
   713     {	
   714 		if (!treeItem->getBranchNum(i)->isHidden())
   715 		{
   716 			treeItem->getBranchObjNum(i)->alignRelativeTo (ref2,true);
   717 
   718 			// append next branch below current one
   719 			ref2.setY(ref2.y() + treeItem->getBranchObjNum(i)->getBBoxSizeWithChildren().height() );
   720 		}
   721     }
   722 }
   723 
   724 
   725 void BranchObj::reposition()
   726 {	
   727 /* TODO testing only
   728 	if (!treeItem->getHeading().isEmpty())
   729 		cout << "BO::reposition  "<<qPrintable(treeItem->getHeading())<<endl;
   730 	else	
   731 		cout << "BO::reposition  ???"<<endl;
   732 //	cout << "  orient="<<orientation<<endl;
   733 */		
   734 
   735 	if (treeItem->depth()==0)
   736 	{
   737 		// only calculate the sizes once. If the deepest LMO 
   738 		// changes its height,
   739 		// all upper LMOs have to change, too.
   740 		calcBBoxSizeWithChildren();
   741 		updateLinkGeometry();	// This update is needed if the scene is resized 
   742 						// due to excessive moving of a FIO
   743 
   744 	    alignRelativeTo ( QPointF (absPos.x(),
   745 			absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   746 		//FIXME-2 qSort (branch.begin(),branch.end(), isAbove);
   747 		positionBBox();	// Reposition bbox and contents
   748 	} else
   749 	{
   750 		// This is only important for moving branches:
   751 		// For editing a branch it isn't called...
   752 	    alignRelativeTo ( QPointF (absPos.x(),
   753 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   754 	}
   755 }
   756 
   757 void BranchObj::unsetAllRepositionRequests()
   758 {
   759 	repositionRequest=false;
   760 	for (int i=0; i<treeItem->branchCount(); ++i)
   761 		treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
   762 }
   763 
   764 
   765 QPolygonF BranchObj::shape()
   766 {
   767 	QPolygonF p;
   768 
   769 	QRectF r=getTotalBBox();
   770 	if (orientation==LinkableMapObj::LeftOfCenter)
   771 		p   <<r.bottomLeft()
   772 			<<r.topLeft()
   773 			<<QPointF (bbox.topLeft().x(), r.topLeft().y() )
   774 			<<bbox.topRight()
   775 			<<bbox.bottomRight()
   776 			<<QPointF (bbox.bottomLeft().x(), r.bottomLeft().y() ) ;
   777 	else		
   778 		p   <<r.bottomRight()
   779 			<<r.topRight()
   780 			<<QPointF (bbox.topRight().x(), r.topRight().y() )
   781 			<<bbox.topLeft()
   782 			<<bbox.bottomLeft()
   783 			<<QPointF (bbox.bottomRight().x(), r.bottomRight().y() ) ;
   784 	return p;
   785 }
   786 
   787 QRectF BranchObj::getTotalBBox()
   788 {
   789 	QRectF r=bbox;
   790 
   791 	if ( ((BranchItem*)treeItem)->isScrolled() ) return r;
   792 
   793 	for (int i=0; i<treeItem->branchCount(); ++i)
   794 		if (!treeItem->getBranchNum(i)->isHidden())
   795 			r=addBBox(treeItem->getBranchObjNum(i)->getTotalBBox(),r);
   796 
   797 /* FIXME-3 lots of occurences of treeItem->getBranchObjNum(i) in branchobj.cpp
   798             better check if they are not NULL and maybe simplify...
   799 			(have been NULL at least in calcBBoxSizeWithChilds...)
   800 */			
   801 
   802 	for (int i=0; i<treeItem->imageCount(); ++i)
   803 		if (!treeItem->isHidden())
   804 			r=addBBox(treeItem->getImageObjNum(i)->getTotalBBox(),r);
   805 	return r;
   806 }
   807 
   808 QRectF BranchObj::getBBoxSizeWithChildren()
   809 {
   810 	return bboxTotal;
   811 }
   812 
   813 void BranchObj::calcBBoxSizeWithChildren()
   814 {	
   815 	// This is initially called only from reposition and
   816 	// and only for mapcenter. So it won't be
   817 	// called more than once for a single user 
   818 	// action
   819 	
   820 
   821 	// Calculate size of LMO including all children (to align them later)
   822 	bboxTotal.setX(bbox.x() );
   823 	bboxTotal.setY(bbox.y() );
   824 
   825 	// if branch is scrolled, ignore children, but still consider floatimages
   826 	BranchItem *bi=(BranchItem*)treeItem;
   827 	if ( bi->isScrolled() ) 
   828 	{
   829 		bboxTotal.setWidth (bbox.width());
   830 		bboxTotal.setHeight(bbox.height());
   831 		return;
   832 	}
   833 	
   834 	if (bi->isHidden())
   835 	{
   836 		bboxTotal.setWidth (0);
   837 		bboxTotal.setHeight(0);
   838 		if (parObj)
   839 		{
   840 			bboxTotal.setX (parObj->x());
   841 			bboxTotal.setY (parObj->y());
   842 		} else
   843 		{
   844 			bboxTotal.setX (bbox.x());
   845 			bboxTotal.setY (bbox.y());
   846 		}
   847 		return;
   848 	}
   849 	
   850 	QRectF r(0,0,0,0);
   851 	QRectF br;
   852 	// Now calculate recursivly
   853 	// sum of heights 
   854 	// maximum of widths 
   855 	// minimum of y
   856 	for (int i=0; i<treeItem->branchCount(); i++)
   857 	{
   858 		if (!bi->getBranchNum(i)->isHidden())
   859 		{
   860 			bi->getBranchObjNum(i)->calcBBoxSizeWithChildren();
   861 			br=bi->getBranchObjNum(i)->getBBoxSizeWithChildren();
   862 			r.setWidth( max (br.width(), r.width() ));
   863 			r.setHeight(br.height() + r.height() );
   864 			if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
   865 		}
   866 	}
   867 	// Add myself and also
   868 	// add width of link to sum if necessary
   869 	if (bi->branchCount()<1)
   870 		bboxTotal.setWidth (bbox.width() + r.width() );
   871 	else	
   872 		bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
   873 	
   874 	bboxTotal.setHeight(max (r.height(),  bbox.height()));
   875 }
   876 
   877 QString BranchObj::getSelectString()
   878 {
   879 	VymModel *model=treeItem->getModel();
   880 	if (model)
   881 		return model->getSelectString (this);
   882 	else
   883 		return QString();
   884 }
   885 
   886 void BranchObj::setAnimation(const AnimPoint &ap)
   887 {
   888 	anim=ap;
   889 }
   890 
   891 bool BranchObj::animate()
   892 {
   893 	anim.animate ();
   894 	if ( anim.isAnimated() )
   895 	{
   896 		setRelPos (anim);
   897 		return true;
   898 	}
   899 	parObj->reposition();	// we might have been relinked meanwhile
   900 	return false;
   901 }
   902