branchobj.cpp
author insilmaril
Thu, 07 May 2009 08:48:53 +0000
changeset 766 7a71a914afdb
parent 760 59614eaf5fbb
child 767 6d2b32f305f9
permissions -rw-r--r--
Started to reanimate flags
     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 //class TextEditor; //FIXME-3
    10 
    11 //extern TextEditor *textEditor;
    12 //extern Main *mainWindow;
    13 //extern FlagRowObj *standardFlagsDefault;
    14 
    15 
    16 /////////////////////////////////////////////////////////////////
    17 // BranchObj
    18 /////////////////////////////////////////////////////////////////
    19 
    20 BranchObj::BranchObj () :OrnamentedObj()	// FIXME-3 needed at all?
    21 {
    22 //    cout << "Const BranchObj ()\n";
    23     setParObj (this);	
    24     init();
    25 }
    26 
    27 BranchObj::BranchObj (QGraphicsScene* s):OrnamentedObj (s)// FIXME-3 needed at all?
    28 {
    29 //    cout << "Const BranchObj (s)  \n";
    30 	parObj=NULL;
    31     scene=s;
    32 	init();
    33 }
    34 
    35 BranchObj::BranchObj (QGraphicsScene* s, LinkableMapObj* p):OrnamentedObj (s)// FIXME-3 needed at all?
    36 {
    37 //    cout << "Const BranchObj (s,p)\n";
    38     scene=s;
    39     setParObj (p);	
    40 	if (treeItem->depth()==1)
    41 		// Calc angle to mapCenter if I am a mainbranch
    42 		// needed for reordering the mainbranches clockwise 
    43 		// around mapcenter 
    44 		angle=getAngle (QPointF (x() - parObj->getChildPos().x() , 
    45 								(y() - parObj->getChildPos().y() ) ) );
    46     init();
    47 }
    48 
    49 BranchObj::~BranchObj ()
    50 {
    51 //	cout << "Destr BranchObj of "<<this<<" ("<<treeItem->getHeading().toStdString()<<")"<<endl;
    52 
    53 	// If I'm animated, I need to un-animate myself first
    54 	if (anim.isAnimated() )
    55 	{
    56 		anim.setAnimated (false);
    57 		model->stopAnimation (this);
    58 	}
    59 
    60 	// Check, if this branch was the last child to be deleted
    61 	// If so, unset the scrolled flags in parent // FIXME-2 better do this in model?
    62 
    63 	/*
    64 	BranchObj *po=(BranchObj*)parObj;
    65 	BranchObj *bo;
    66 	if (po)
    67 	{
    68 		bo=((BranchObj*)parObj)->getLastBranch();
    69 		if (bo) po->unScroll();
    70 	}
    71 	*/
    72 	clear();
    73 }
    74 
    75 bool BranchObj::operator< ( const BranchObj & other )
    76 {
    77     return  angle < other.angle;
    78 }
    79 
    80 bool BranchObj::operator== ( const BranchObj & other )
    81 {
    82     return angle == other.angle;
    83 }
    84 
    85 void BranchObj::init () 
    86 {
    87 	if (parObj)
    88 	{
    89 		absPos=getRandPos();
    90 		absPos+=parObj->getChildPos();
    91 	}
    92 
    93     setChildObj(this);
    94 
    95 	includeImagesVer=false;
    96 	includeImagesHor=false;
    97 }
    98 
    99 void BranchObj::copy (BranchObj* other)
   100 {
   101     OrnamentedObj::copy(other);
   102 
   103 	for (int i=0; i<other->floatimage.size(); ++i)
   104 		addFloatImage  (other->floatimage.at(i));
   105 	
   106 	setVisibility (other->visible);
   107 
   108 	angle=other->angle;
   109 
   110     positionBBox();
   111 }
   112 
   113 void BranchObj::clear() 
   114 {
   115 	//setVisibility (true); //FIXME-4 needed?
   116 
   117 	while (!floatimage.isEmpty())
   118 		delete floatimage.takeFirst();
   119 
   120 	while (!xlink.isEmpty())
   121 		delete xlink.takeFirst();
   122 }
   123 
   124 bool isAbove (BranchObj* a, BranchObj *b)
   125 {
   126 	if (a->angle < b->angle)
   127 		return true;
   128 	else	
   129 		return false;
   130 }
   131 
   132 void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPointF m, int off)
   133 {
   134 	// Temporary link to lmo
   135 	// m is position of mouse pointer 
   136 	// offset 0: default 1: below lmo   -1 above lmo  (if possible)
   137 
   138 
   139 	BranchObj* o=(BranchObj*)(lmo);
   140 	if (!parObjTmpBuf) 
   141 		parObjTmpBuf=parObj;
   142 
   143 	// ignore mapcenter and mainbranch
   144 	if (treeItem->depth()<2) off=0;
   145 	if (off==0)
   146 		link2ParPos=false;
   147 	else
   148 		link2ParPos=true;
   149 	parObj=o;
   150 
   151 	// FIXME-2 depth=parObj->getDepth()+1;
   152 
   153 	// setLinkStyle calls updateLink, only set it once
   154 	if (style!=getDefLinkStyle() ) setLinkStyle (getDefLinkStyle());
   155 
   156 	// Move temporary to new position at destination
   157 	// Usually the positioning would be done by reposition(),
   158 	// but then also the destination branch would "Jump" around...
   159 	// Better just do it approximately
   160 	if (treeItem->depth()==1)
   161 	{	// new parent is the mapcenter itself
   162 
   163 		QPointF p= normalise ( QPointF (m.x() - o->getChildPos().x(),
   164 									  m.y() - o->getChildPos().y() ));
   165 		if (p.x()<0) p.setX( p.x()-bbox.width() );
   166 		move2RelPos (p);
   167 	} else
   168 	{	
   169 		qreal y;
   170 		if (off==0)
   171 		{
   172 			// new parent is just a branch, link to it
   173 			QRectF t=o->getBBoxSizeWithChildren();
   174 			if (o->getTreeItem()->getLastBranch())
   175 				y=t.y() + t.height() ;
   176 			else
   177 				y=t.y();
   178 
   179 		} else
   180 		{
   181 			if (off<0)
   182 				// we want to link above lmo
   183 				y=o->y() - height() + 5;
   184 			else	
   185 				// we want to link below lmo
   186 				// Bottom of sel should be 5 pixels above
   187 				// the bottom of the branch _below_ the target:
   188 				// Don't try to find that branch, guess 12 pixels
   189 				y=o->getChildPos().y()  -height() + 12; 
   190 		}	
   191 		if (o->getOrientation()==LinkableMapObj::LeftOfCenter)
   192 			move ( o->getChildPos().x() - linkwidth, y );
   193 		else	
   194 			move (o->getChildPos().x() + linkwidth, y );
   195 	}	
   196 
   197 	// updateLink is called implicitly in move
   198 	requestReposition();	
   199 }
   200 
   201 void BranchObj::unsetParObjTmp()
   202 {
   203 	if (parObjTmpBuf) 
   204 	{
   205 		link2ParPos=false;
   206 		parObj=parObjTmpBuf;
   207 		parObjTmpBuf=NULL;
   208 		//FIXME-2 depth=parObj->getDepth()+1;
   209 		setLinkStyle (getDefLinkStyle() );
   210 		updateLink();
   211 	}		
   212 }
   213 
   214 void BranchObj::setVisibility(bool v, int toDepth)
   215 {
   216 	BranchItem *bi=(BranchItem*)treeItem;
   217     if (bi->depth() <= toDepth)
   218     {
   219 		frame->setVisibility(v);
   220 		heading->setVisibility(v);
   221 		systemFlags->setVisibility(v);
   222 		standardFlags->setVisibility(v);
   223 		LinkableMapObj::setVisibility (v);
   224 		int i;
   225 		for (i=0; i<floatimage.size(); ++i)
   226 			floatimage.at(i)->setVisibility (v);
   227 		for (i=0; i<xlink.size(); ++i)	
   228 			xlink.at(i)->setVisibility ();	
   229 
   230 		// Only change children, if I am not scrolled
   231 		if (! bi->isScrolled() && (bi->depth() < toDepth))
   232 		{
   233 			// Now go recursivly through all children
   234 			for (i=0; i<treeItem->branchCount(); ++i)
   235 				treeItem->getBranchObjNum(i)->setVisibility (v,toDepth);	
   236 		}
   237     } // depth <= toDepth	
   238 	requestReposition();
   239 }	
   240 
   241 void BranchObj::setVisibility(bool v)
   242 {
   243     setVisibility (v,MAX_DEPTH);
   244 }
   245 
   246 
   247 void BranchObj::setLinkColor ()
   248 {
   249 	// Overloaded from LinkableMapObj
   250 	// BranchObj can use color of heading
   251 
   252 	if (model)
   253 	{
   254 		if (model->getMapLinkColorHint()==HeadingColor)
   255 			LinkableMapObj::setLinkColor (heading->getColor() );
   256 		else	
   257 			LinkableMapObj::setLinkColor ();
   258 	}		
   259 }
   260 
   261 void BranchObj::setColorSubtree(QColor col)
   262 {
   263 	setColor (col);
   264 	for (int i=0; i<treeItem->branchCount(); ++i)
   265 		treeItem->getBranchObjNum(i)->setColorSubtree(col);
   266 }
   267 
   268 void BranchObj::updateContentSize()
   269 {
   270 	calcBBoxSize();
   271 	positionBBox();
   272 	requestReposition();
   273 }
   274 
   275 void BranchObj::positionContents()
   276 {
   277     for (int i=0; i<floatimage.size(); ++i )
   278 		floatimage.at(i)->reposition();
   279 	OrnamentedObj::positionContents();
   280 }
   281 
   282 void BranchObj::move (double x, double y)
   283 {
   284 	OrnamentedObj::move (x,y);
   285     for (int i=0; i<floatimage.size(); ++i )
   286 		floatimage.at(i)->reposition();
   287     positionBBox();
   288 }
   289 
   290 void BranchObj::move (QPointF p)
   291 {
   292 	move (p.x(), p.y());
   293 }
   294 
   295 void BranchObj::moveBy (double x, double y)
   296 {
   297 	OrnamentedObj::moveBy (x,y);
   298 	for (int i=0; i<treeItem->branchCount(); ++i)
   299 		treeItem->getBranchObjNum(i)->moveBy (x,y);
   300     positionBBox();
   301 }
   302 	
   303 void BranchObj::moveBy (QPointF p)
   304 {
   305 	moveBy (p.x(), p.y());
   306 }
   307 
   308 
   309 void BranchObj::positionBBox()
   310 {
   311 	QPointF ap=getAbsPos();
   312 	bbox.moveTopLeft (ap);
   313 	positionContents();
   314 
   315 	// set the frame
   316 	frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
   317 
   318 	// Update links to other branches
   319 	for (int i=0; i<xlink.size(); ++i)
   320 		xlink.at(i)->updateXLink();
   321 }
   322 
   323 void BranchObj::calcBBoxSize()
   324 {
   325     QSizeF heading_r=heading->getSize();
   326     qreal heading_w=(qreal) heading_r.width() ;
   327     qreal heading_h=(qreal) heading_r.height() ;
   328     QSizeF sysflags_r; //FIXME-1 =systemFlags->getSize();
   329 	qreal sysflags_h=0;//sysflags_r.height();
   330 	qreal sysflags_w=0;//sysflags_r.width();
   331     QSizeF stanflags_r; //FIXME-1 =standardFlags->getSize();
   332 	qreal stanflags_h=0; //stanflags_r.height();
   333 	qreal stanflags_w=0; //stanflags_r.width();
   334     qreal w;
   335     qreal h;
   336 
   337 	// set width to sum of all widths
   338 	w=heading_w + sysflags_w + stanflags_w;
   339 	// set height to maximum needed height
   340 	h=max (sysflags_h,stanflags_h);
   341 	h=max (h,heading_h);
   342 
   343 	// Save the dimension of flags and heading
   344 	ornamentsBBox.setSize ( QSizeF(w,h));
   345 
   346 	// clickBox includes Flags and Heading
   347     clickBox.setSize (ornamentsBBox.size() );
   348 
   349 	// Floatimages 
   350 	QPointF rp;
   351 
   352 	topPad=botPad=leftPad=rightPad=0;
   353 	if (includeImagesVer || includeImagesHor)
   354 	{
   355 		if (treeItem->imageCount()>0)
   356 		{
   357 			for (int i=0; i<floatimage.size(); ++i )
   358 			{
   359 				rp=floatimage.at(i)->getRelPos();
   360 				if (includeImagesVer)
   361 				{
   362 					if (rp.y() < 0) 
   363 						topPad=max (topPad,-rp.y()-h);
   364 					if (rp.y()+floatimage.at(i)->height() > 0)
   365 						botPad=max (botPad,rp.y()+floatimage.at(i)->height());
   366 				}		
   367 				if (includeImagesHor)
   368 				{
   369 					if (orientation==LinkableMapObj::RightOfCenter)
   370 					{
   371 						if (-rp.x()-w > 0) 
   372 							leftPad=max (leftPad,-rp.x()-w);
   373 						if (rp.x()+floatimage.at(i)->width() > 0)
   374 							rightPad=max (rightPad,rp.x()+floatimage.at(i)->width());
   375 					} else
   376 					{
   377 						if (rp.x()< 0) 
   378 							leftPad=max (leftPad,-rp.x());
   379 						if (rp.x()+floatimage.at(i)->width() > w)
   380 							rightPad=max (rightPad,rp.x()+floatimage.at(i)->width()-w);
   381 					}
   382 				}		
   383 			}	
   384 		}	
   385 		h+=topPad+botPad;
   386 		w+=leftPad+rightPad;
   387 	}
   388 
   389 	// Frame thickness
   390     w+=frame->getPadding();
   391     h+=frame->getPadding();
   392 	
   393 	// Finally set size
   394     bbox.setSize (QSizeF (w,h));
   395 }
   396 
   397 void BranchObj::setDockPos()
   398 {
   399 	// Sets childpos and parpos depending on orientation
   400 	if (getOrientation()==LinkableMapObj::LeftOfCenter )
   401     {
   402 		childPos=QPointF (
   403 			ornamentsBBox.bottomLeft().x(), 
   404 			bottomlineY);
   405 		parPos=QPointF (
   406 			ornamentsBBox.bottomRight().x(),
   407 			bottomlineY);
   408     } else
   409     {
   410 		childPos=QPointF (
   411 			ornamentsBBox.bottomRight().x(), 
   412 			bottomlineY);
   413 		parPos=QPointF (
   414 			ornamentsBBox.bottomLeft().x(),
   415 			bottomlineY);
   416     }
   417 }
   418 
   419 void BranchObj::updateHeading()
   420 {
   421 	if (!treeItem)
   422 	{
   423 		qWarning ("BranchObj::udpateHeading treeItem==NULL");
   424 		return;
   425 	}
   426 	heading->setText (treeItem->getHeading() );
   427 	updateContentSize();
   428 }
   429 
   430 QString BranchObj::saveToDir (const QString &tmpdir,const QString &prefix, const QPointF& offset)
   431 {
   432 	// Cloudy stuff can be hidden during exports
   433 	// FIXME-1 if (hidden) return "";
   434 
   435 	// Update of note is usually done while unselecting a branch
   436 	// if (isNoteInEditor) getNoteFromTextEditor();		//FIXME-2 moved to TreeItem
   437 	
   438     QString s,a;
   439 	/*
   440 	QString scrolledAttr;
   441 	if ( ((BranchItem*)treeItem)->isScrolled() ) 
   442 		scrolledAttr=attribut ("scrolled","yes");
   443 	else
   444 		scrolledAttr="";
   445 
   446 	// save area, if not scrolled
   447 	QString areaAttr;
   448 	if (!((BranchItem*) (treeItem->parent()) )->isScrolled() )
   449 	{
   450 		areaAttr=
   451 			attribut("x1",QString().setNum(absPos.x()-offset.x())) +
   452 			attribut("y1",QString().setNum(absPos.y()-offset.y())) +
   453 			attribut("x2",QString().setNum(absPos.x()+width()-offset.x())) +
   454 			attribut("y2",QString().setNum(absPos.y()+height()-offset.y()));
   455 
   456 	} else
   457 		areaAttr="";
   458 	
   459 	// Providing an ID for a branch makes export to XHTML easier
   460 	QString idAttr;
   461 	if (treeItem->xlinkCount()>0)
   462 		idAttr=attribut ("id",model->getSelectString(this)); //TODO directly access model
   463 	else
   464 		idAttr="";
   465 
   466     s=beginElement ("branch" 
   467 		+getOrnXMLAttr() 
   468 		+scrolledAttr 
   469 		+areaAttr 
   470 		+idAttr 
   471 		+getIncludeImageAttr() );
   472     incIndent();
   473 
   474 	// save heading
   475     s+=valueElement("heading", treeItem->getHeading(),
   476 		attribut ("textColor",QColor(heading->getColor()).name()));
   477 
   478 	// Save frame
   479 	if (frame->getFrameType()!=FrameObj::NoFrame) 
   480 		s+=frame->saveToDir ();
   481 
   482 	// save names of flags set
   483 	s+=standardFlags->saveToDir(tmpdir,prefix,0);
   484 	
   485 	// Save FloatImages
   486 	for (int i=0; i<floatimage.size(); ++i)
   487 		s+=floatimage.at(i)->saveToDir (tmpdir,prefix);
   488 
   489 	// save note
   490 	if (!treeItem->getNoteObj().isEmpty() )
   491 		s+=treeItem->getNoteObj().saveToDir();
   492 	
   493 	// Save branches
   494 	for (int i=0; i<treeItem->branchCount(); ++i)
   495 		s+=treeItem->getBranchObjNum(i)->saveToDir(tmpdir,prefix,offset);
   496 
   497 	// Save XLinks
   498 	QString ol;	// old link
   499 	QString cl;	// current link
   500 	for (int i=0; i<xlink.size(); ++i)
   501 	{
   502 		cl=xlink.at(i)->saveToDir();
   503 		if (cl!=ol)
   504 		{
   505 			s+=cl;
   506 			ol=cl;
   507 		} else
   508 		{
   509 			qWarning (QString("Ignoring of duplicate xLink in %1").arg(treeItem->getHeading()));
   510 		}
   511 	}	
   512 
   513     decIndent();
   514     s+=endElement   ("branch");
   515     return s;
   516 */	
   517 }
   518 
   519 void BranchObj::addXLink (XLinkObj *xlo)
   520 {
   521 	xlink.append (xlo);
   522 	
   523 }
   524 
   525 void BranchObj::removeXLinkRef (XLinkObj *xlo)
   526 {
   527 	xlink.removeAt (xlink.indexOf(xlo));
   528 }
   529 
   530 void BranchObj::deleteXLink(XLinkObj *xlo)
   531 {
   532 	xlo->deactivate();
   533 	if (!xlo->isUsed()) delete (xlo);
   534 }
   535 
   536 void BranchObj::deleteXLinkAt (int i)
   537 {
   538 	XLinkObj *xlo=xlink.at(i);
   539 	xlo->deactivate();
   540 	if (!xlo->isUsed()) delete(xlo);
   541 }
   542 
   543 XLinkObj* BranchObj::XLinkAt (int i)
   544 {
   545 	return xlink.at(i);
   546 }
   547 
   548 BranchObj* BranchObj::XLinkTargetAt (int i)
   549 {
   550 	if (i>=0 && i<xlink.size())
   551 	{
   552 		if (xlink.at(i))
   553 			return xlink.at(i)->otherBranch (this);
   554 	}
   555 	return NULL;
   556 }
   557 
   558 void BranchObj::setIncludeImagesVer(bool b)
   559 {
   560 	includeImagesVer=b;
   561 	calcBBoxSize();
   562 	positionBBox();
   563 	requestReposition();
   564 }
   565 
   566 bool BranchObj::getIncludeImagesVer()
   567 {
   568 	return includeImagesVer;
   569 }
   570 
   571 void BranchObj::setIncludeImagesHor(bool b)
   572 {
   573 	includeImagesHor=b;
   574 	calcBBoxSize();
   575 	positionBBox();
   576 	requestReposition();
   577 }
   578 
   579 bool BranchObj::getIncludeImagesHor()
   580 {
   581 	return includeImagesHor;
   582 }
   583 
   584 QString BranchObj::getIncludeImageAttr()
   585 {
   586 	QString a;
   587 	if (includeImagesVer)
   588 		a=attribut ("incImgV","true");
   589 	else
   590 		a=attribut ("incImgV","false");
   591 	if (includeImagesHor)
   592 		a+=attribut ("incImgH","true");
   593 	else
   594 		a+=attribut ("incImgH","false");
   595 	return a;	
   596 }
   597 
   598 FloatImageObj* BranchObj::addFloatImage ()
   599 {
   600 	FloatImageObj *newfi=new FloatImageObj (scene,this);
   601 	floatimage.append (newfi);
   602 	if ( ((BranchItem*)treeItem)->hasScrolledParent((BranchItem*)treeItem) )
   603 		newfi->setVisibility (false);
   604 	else	
   605 		newfi->setVisibility(visible);
   606 		/*
   607 	calcBBoxSize();
   608 	positionBBox();
   609 	*/
   610 	requestReposition();
   611 	return newfi;
   612 }
   613 
   614 FloatImageObj* BranchObj::addFloatImage (FloatImageObj *fio)
   615 {
   616 	FloatImageObj *newfi=new FloatImageObj (scene,this);
   617 	floatimage.append (newfi);
   618 	newfi->copy (fio);
   619 	if (((BranchItem*)treeItem)->hasScrolledParent((BranchItem*)treeItem) )
   620 		newfi->setVisibility (false);
   621 	else	
   622 		newfi->setVisibility(visible);
   623 		/*
   624 	calcBBoxSize();
   625 	positionBBox();
   626 	*/
   627 	requestReposition();
   628 	return newfi;
   629 }
   630 
   631 FloatImageObj* BranchObj::getFirstFloatImage ()
   632 {
   633     return floatimage.first();
   634 }
   635 
   636 FloatImageObj* BranchObj::getLastFloatImage ()
   637 {
   638     return floatimage.last();
   639 }
   640 
   641 FloatImageObj* BranchObj::getFloatImageNum (const uint &i)
   642 {
   643     return floatimage.at(i);
   644 }
   645 
   646 void BranchObj::removeFloatImage (FloatImageObj *fio)
   647 {
   648 	int i=floatimage.indexOf (fio);
   649 	if (i>-1) delete (floatimage.takeAt (i));
   650 	calcBBoxSize();
   651 	positionBBox();
   652 	requestReposition();
   653 }
   654 
   655 void BranchObj::savePosInAngle ()
   656 {
   657 	// Save position in angle
   658 	for (int i=0; i<treeItem->branchCount(); ++i)
   659 		treeItem->getBranchObjNum(i)->angle=i;
   660 }
   661 
   662 void BranchObj::setDefAttr (BranchModification mod)
   663 {
   664 	int fontsize;
   665 	switch (treeItem->depth())
   666 	{
   667 		case 0: fontsize=16; break;
   668 		case 1: fontsize=12; break;
   669 		default: fontsize=10; break;
   670 	}	
   671 
   672 	setLinkColor ();
   673 	setLinkStyle(getDefLinkStyle());
   674 	QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
   675 	font.setPointSize(fontsize);
   676 	heading->setFont(font );
   677 
   678 	if (mod==NewBranch)
   679 		setColor (treeItem->getHeadingColor() );
   680 	calcBBoxSize();
   681 }
   682 
   683 void BranchObj::removeBranchHere(BranchObj* borem)	// FIXME-2 getNum no longer available
   684 {
   685 /*
   686 	// This removes the branch bo from list, but 
   687 	// inserts its children at the place of bo
   688 	BranchObj *bo;
   689 	bo=borem->getLastBranch();
   690 	int pos=borem->getNum();
   691 	while (bo)
   692 	{
   693 		bo->linkTo (this,pos+1);
   694 		bo=borem->getLastBranch();
   695 	}	
   696 	removeBranch (borem);
   697 	*/
   698 }
   699 
   700 void BranchObj::removeChildren()	// FIXME-3 not needed here
   701 {
   702 	clear();
   703 }
   704 
   705 void BranchObj::removeBranch(BranchObj* bo)	// FIXME-2 not needed here
   706 {
   707 /*
   708     // if bo is not in branch remove returns false, we
   709     // don't care...
   710 	
   711 	int i=branch.indexOf(bo);
   712     if (i>=0)
   713 	{
   714 		delete (bo);
   715 		branch.removeAt (i);
   716 	} else
   717 		qWarning ("BranchObj::removeBranch tried to remove non existing branch?!\n");
   718 	requestReposition();
   719 	*/
   720 }
   721 
   722 void BranchObj::removeBranchPtr(BranchObj* bo)	// FIXME-3 not needed here
   723 {
   724 /*
   725 	int i=branch.indexOf(bo);
   726 	
   727 	if (i>=0)
   728 		branch.removeAt (i);
   729 	else	
   730 		qWarning ("BranchObj::removeBranchPtr tried to remove non existing branch?!\n");
   731 	requestReposition();
   732 */	
   733 }
   734 
   735 bool BranchObj::canMoveBranchUp() // FIXME-1 move to BranchItem
   736 {
   737 /*
   738 	if (!parObj || depth==1) return false;
   739 	BranchObj* par=(BranchObj*)parObj;
   740 	if (this==par->getTreeItem()->getFirstBranch())
   741 		return false;
   742 	else
   743 		return true;
   744 		*/
   745 return false;
   746 }
   747 
   748 BranchObj* BranchObj::moveBranchUp(BranchObj* bo1) // FIXME-1
   749 {
   750 /*
   751 	savePosInAngle();
   752     int i=branch.indexOf(bo1);
   753     if (i>0) 
   754 	{	// -1 if bo1 not found 
   755 		treeItem->getBranchObjNum(i)->angle--;
   756 		treeItem->getBranchObjNum(i-1)->angle++;
   757 		qSort (branch.begin(),branch.end(), isAbove);
   758 		return treeItem->getBranchObjNum(i);
   759 	} else
   760 */	
   761 		return NULL;
   762 }
   763 
   764 bool BranchObj::canMoveBranchDown() //FIXME-1 move to BranchItem
   765 {
   766 	/* 
   767 	if (!parObj|| depth==1) return false;
   768 	BranchObj* par=(BranchObj*)parObj;
   769 	if (this==par->getTreeItem()->getLastBranch())
   770 		return false;
   771 	else
   772 		return true;
   773 	*/
   774 return false;	
   775 }
   776 
   777 BranchObj* BranchObj::moveBranchDown(BranchObj* bo1)// FIXME-1
   778 {
   779 /*
   780 	savePosInAngle();
   781     int i=branch.indexOf(bo1);
   782 	int j;
   783 	if (i <treeItem->branchCount())
   784 	{
   785 		j = i+1;
   786 		treeItem->getBranchObjNum(i)->angle++;
   787 		treeItem->getBranchObjNum(j)->angle--;
   788 		qSort (branch.begin(),branch.end(), isAbove);
   789 		return treeItem->getBranchObjNum(i);
   790 	} else
   791 */	
   792 		return NULL;
   793 }
   794 
   795 void BranchObj::sortChildren() //FIXME-2  
   796 {
   797 /*
   798 	int childCount=branch.count(); 
   799 	int curChildIndex;
   800 	bool madeChanges=false;
   801 	do
   802 	{
   803 		madeChanges=false;
   804 		for(curChildIndex=1;curChildIndex<childCount;curChildIndex++){
   805 			BranchObj* curChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex);
   806 			BranchObj* prevChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex-1);
   807 			if(prevChild->heading->text().compare(curChild->heading->text())>0)
   808 			{
   809 				this->moveBranchUp(curChild);
   810 				madeChanges=true;
   811 			}
   812 		}
   813 	}while(madeChanges);
   814 */
   815 }
   816 
   817 void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
   818 {
   819 	qreal th = bboxTotal.height();	
   820 	int depth=treeItem->depth();
   821 // TODO testing
   822 /*
   823 
   824 	QString h=QString (depth,' ');
   825 	h+=treeItem->getHeading();
   826 	h+=QString (15,' ');
   827 	h.truncate (15);
   828 	QPointF pp; if (parObj) pp=parObj->getChildPos();
   829 	cout << "BO::alignRelTo ";
   830 	cout<<h.toStdString();
   831 	cout << "    d="<<depth<<
   832 //cout<<  "  ref="<<ref<<
   833       	"  bbox.tL="<<bboxTotal.topLeft()<<
   834 		"  absPos="<<absPos<<
   835 //		"  relPos="<<relPos<<
   836 //		"  parPos="<<pp<<
   837 		"  w="<<bbox.width()<<
   838 		"  h="<<bbox.height()<<
   839 //		"  orient="<<orientation<<
   840 //		"  alignSelf="<<alignSelf<<
   841 //		"  scrolled="<<((BranchItem*)treeItem)->isScrolled()<<
   842 //		"  pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
   843 //		"  hidden="<<hidden<<
   844 		"  th="<<th<<
   845 		endl;
   846 */
   847 
   848 	setOrientation();
   849 	//updateLink();
   850 
   851 	if (depth==1 && parObj)
   852 	{
   853 		// Position relatively, if needed
   854 		//if (useRelPos) move2RelPos (relPos.x(), relPos.y());
   855 
   856 		// Calc angle to mapCenter if I am a mainbranch
   857 		// needed for reordering the mainbranches clockwise 
   858 		// around mapcenter 
   859 		angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ), 
   860 								(int)(y() - parObj->getChildPos().y() ) ) );
   861 	}							
   862 	if (depth>1)
   863     {
   864 		// Align myself depending on orientation and parent, but
   865 		// only if I am not a mainbranch or mapcenter itself
   866 
   867 		if (anim.isAnimated())
   868 		{
   869 			move2RelPos(anim);
   870 		} else
   871 		{
   872 			LinkableMapObj::Orientation o;
   873 			o=parObj->getOrientation();
   874 			if (alignSelf)
   875 				switch (orientation) 
   876 				{
   877 					case LinkableMapObj::LeftOfCenter:
   878 						move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
   879 						//move (ref.x() , ref.y() + (th-bbox.height())/2 );
   880 					break;
   881 					case LinkableMapObj::RightOfCenter:	
   882 						move (ref.x() , ref.y() + (th-bbox.height())/2  );
   883 					break;
   884 					default:
   885 						qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
   886 					break;
   887 			}
   888 		}
   889     }		
   890 
   891 	if ( ((BranchItem*)treeItem)->isScrolled() ) return;
   892 
   893     // Set reference point for alignment of children
   894     QPointF ref2;
   895     if (orientation==LinkableMapObj::LeftOfCenter)
   896 		ref2.setX(bbox.topLeft().x() - linkwidth);
   897     else	
   898 		ref2.setX(bbox.topRight().x() + linkwidth);
   899 
   900 	if (depth==1)
   901 		ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
   902 	else	
   903 		ref2.setY(ref.y() );	
   904 
   905     // Align the children depending on reference point 
   906 	for (int i=0; i<treeItem->branchCount(); ++i)
   907     {	
   908 		if (!treeItem->getBranchNum(i)->isHidden())
   909 		{
   910 			treeItem->getBranchObjNum(i)->alignRelativeTo (ref2,true);
   911 
   912 			// append next branch below current one
   913 			ref2.setY(ref2.y() + treeItem->getBranchObjNum(i)->getBBoxSizeWithChildren().height() );
   914 		}
   915     }
   916 }
   917 
   918 
   919 void BranchObj::reposition()
   920 {	
   921 /* TODO testing only
   922 	if (!treeItem->getHeading().isEmpty())
   923 		cout << "BO::reposition  "<<qPrintable(treeItem->getHeading())<<endl;
   924 	else	
   925 		cout << "BO::reposition  ???"<<endl;
   926 //	cout << "  orient="<<orientation<<endl;
   927 */		
   928 
   929 	if (treeItem->depth()==0)
   930 	{
   931 		// only calculate the sizes once. If the deepest LMO 
   932 		// changes its height,
   933 		// all upper LMOs have to change, too.
   934 		calcBBoxSizeWithChildren();
   935 		updateLink();	// This update is needed if the scene is resized 
   936 						// due to excessive moving of a FIO
   937 
   938 	    alignRelativeTo ( QPointF (absPos.x(),
   939 			absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   940 		//FIXME-2 qSort (branch.begin(),branch.end(), isAbove);
   941 		positionBBox();	// Reposition bbox and contents
   942 	} else
   943 	{
   944 		// This is only important for moving branches:
   945 		// For editing a branch it isn't called...
   946 	    alignRelativeTo ( QPointF (absPos.x(),
   947 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   948 	}
   949 }
   950 
   951 void BranchObj::unsetAllRepositionRequests()
   952 {
   953 	repositionRequest=false;
   954 	for (int i=0; i<treeItem->branchCount(); ++i)
   955 		treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
   956 }
   957 
   958 
   959 QPolygonF BranchObj::shape()
   960 {
   961 	QPolygonF p;
   962 
   963 	QRectF r=getTotalBBox();
   964 	if (orientation==LinkableMapObj::LeftOfCenter)
   965 		p   <<r.bottomLeft()
   966 			<<r.topLeft()
   967 			<<QPointF (bbox.topLeft().x(), r.topLeft().y() )
   968 			<<bbox.topRight()
   969 			<<bbox.bottomRight()
   970 			<<QPointF (bbox.bottomLeft().x(), r.bottomLeft().y() ) ;
   971 	else		
   972 		p   <<r.bottomRight()
   973 			<<r.topRight()
   974 			<<QPointF (bbox.topRight().x(), r.topRight().y() )
   975 			<<bbox.topLeft()
   976 			<<bbox.bottomLeft()
   977 			<<QPointF (bbox.bottomRight().x(), r.bottomRight().y() ) ;
   978 	return p;
   979 }
   980 
   981 QRectF BranchObj::getTotalBBox()
   982 {
   983 	QRectF r=bbox;
   984 
   985 	if ( ((BranchItem*)treeItem)->isScrolled() ) return r;
   986 
   987 	for (int i=0; i<treeItem->branchCount(); ++i)
   988 		if (!treeItem->getBranchNum(i)->isHidden())
   989 			r=addBBox(treeItem->getBranchObjNum(i)->getTotalBBox(),r);
   990 
   991 /* FIXME-3 lots of occurences of treeItem->getBranchObjNum(i) in branchobj.cpp
   992             better check if they are not NULL and maybe simplify...
   993 			(have been NULL at least in calcBBoxSizeWithChilds...)
   994 */			
   995 
   996 /*
   997 	FIXME-1 for (int i=0; i<floatimage.size(); ++i)
   998 		if (!floatimage.at(i)->isHidden())
   999 			r=addBBox(floatimage.at(i)->getTotalBBox(),r);
  1000 	*/	
  1001 	return r;
  1002 }
  1003 
  1004 QRectF BranchObj::getBBoxSizeWithChildren()
  1005 {
  1006 	return bboxTotal;
  1007 }
  1008 
  1009 void BranchObj::calcBBoxSizeWithChildren()
  1010 {	
  1011 	// This is initially called only from reposition and
  1012 	// and only for mapcenter. So it won't be
  1013 	// called more than once for a single user 
  1014 	// action
  1015 	
  1016 
  1017 	// Calculate size of LMO including all children (to align them later)
  1018 	bboxTotal.setX(bbox.x() );
  1019 	bboxTotal.setY(bbox.y() );
  1020 
  1021 	// if branch is scrolled, ignore children, but still consider floatimages
  1022 	BranchItem *bi=(BranchItem*)treeItem;
  1023 	if ( bi->isScrolled() ) 
  1024 	{
  1025 		bboxTotal.setWidth (bbox.width());
  1026 		bboxTotal.setHeight(bbox.height());
  1027 		return;
  1028 	}
  1029 	
  1030 	if (bi->isHidden())
  1031 	{
  1032 		bboxTotal.setWidth (0);
  1033 		bboxTotal.setHeight(0);
  1034 		if (parObj)
  1035 		{
  1036 			bboxTotal.setX (parObj->x());
  1037 			bboxTotal.setY (parObj->y());
  1038 		} else
  1039 		{
  1040 			bboxTotal.setX (bbox.x());
  1041 			bboxTotal.setY (bbox.y());
  1042 		}
  1043 		return;
  1044 	}
  1045 	
  1046 	QRectF r(0,0,0,0);
  1047 	QRectF br;
  1048 	// Now calculate recursivly
  1049 	// sum of heights 
  1050 	// maximum of widths 
  1051 	// minimum of y
  1052 	for (int i=0; i<treeItem->branchCount(); i++)
  1053 	{
  1054 		if (!bi->getBranchNum(i)->isHidden())
  1055 		{
  1056 			bi->getBranchObjNum(i)->calcBBoxSizeWithChildren();
  1057 			br=bi->getBranchObjNum(i)->getBBoxSizeWithChildren();
  1058 			r.setWidth( max (br.width(), r.width() ));
  1059 			r.setHeight(br.height() + r.height() );
  1060 			if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
  1061 		}
  1062 	}
  1063 	// Add myself and also
  1064 	// add width of link to sum if necessary
  1065 	if (bi->branchCount()<1)
  1066 		bboxTotal.setWidth (bbox.width() + r.width() );
  1067 	else	
  1068 		bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
  1069 	
  1070 	bboxTotal.setHeight(max (r.height(),  bbox.height()));
  1071 }
  1072 
  1073 /*
  1074 void BranchObj::select()	// FIXME-4 try to get rid of this in BO completely
  1075 {
  1076 	cout << "BO::select()\n";
  1077 	textEditor->setText(treeItem->getNoteObj().getNote() );
  1078 	QString fnh=treeItem->getNoteObj().getFilenameHint();
  1079 	if (fnh!="")
  1080 		textEditor->setFilenameHint(treeItem->getNoteObj().getFilenameHint() );
  1081 	else	
  1082 		textEditor->setFilenameHint(getHeading() );
  1083 	textEditor->setFontHint (treeItem->getNoteObj().getFontHint() );
  1084 	//isNoteInEditor=true;
  1085 
  1086 	// set selected and visible
  1087     LinkableMapObj::select();
  1088 
  1089     //if (po)	po->setLastSelectedBranch(this);  needed?
  1090 		
  1091 	// temporary unscroll, if we have scrolled parents somewhere
  1092 	if (parObj) ((BranchObj*)(parObj))->tmpUnscroll();
  1093 
  1094 	//moved to vymmodel or vymview...
  1095 	// Show URL and link in statusbar
  1096 	QString status;
  1097 	if (!url.isEmpty()) status+="URL: "+url+"  ";
  1098 	if (!vymLink.isEmpty()) status+="Link: "+vymLink;
  1099 	if (!status.isEmpty()) mainWindow->statusMessage (status);
  1100 
  1101 	// Update Toolbar
  1102 	updateFlagsToolbar();
  1103 
  1104 	// Update actions
  1105 	model->updateActions();
  1106 }
  1107 	*/
  1108 
  1109 /*
  1110 void BranchObj::unselect()	//FIXME-4 should not be needed
  1111 {
  1112 	cout << "BO::unselect()\n";
  1113 	LinkableMapObj::unselect();
  1114 	// Delete any messages like vymLink in StatusBar
  1115 	mainWindow->statusMessage ("");		//this causes segfault, when MainWindow is already gone in global destructor on quitting vym
  1116 
  1117 	// Save current note
  1118 	if (isNoteInEditor) getNoteFromTextEditor();
  1119 	isNoteInEditor=false;
  1120 
  1121 	// reset temporary unscroll, if we have scrolled parents somewhere
  1122 	if (parObj) ((BranchObj*)(parObj))->resetTmpUnscroll();
  1123 
  1124 	// Erase content of editor 
  1125 	textEditor->setInactive();
  1126 
  1127 	// unselect all buttons in toolbar
  1128 	standardFlagsDefault->updateToolbar();
  1129 }
  1130 */	
  1131 
  1132 QString BranchObj::getSelectString()
  1133 {
  1134 	return model->getSelectString (this);
  1135 }
  1136 
  1137 void BranchObj::setAnimation(const AnimPoint &ap)
  1138 {
  1139 	anim=ap;
  1140 }
  1141 
  1142 bool BranchObj::animate()
  1143 {
  1144 	anim.animate ();
  1145 	if ( anim.isAnimated() )
  1146 	{
  1147 		setRelPos (anim);
  1148 		return true;
  1149 	}
  1150 	parObj->reposition();	// we might have been relinked meanwhile
  1151 	return false;
  1152 }
  1153