branchobj.cpp
author insilmaril
Wed, 29 Apr 2009 18:46:31 +0000
changeset 760 59614eaf5fbb
parent 757 c6908bc17d78
child 766 7a71a914afdb
permissions -rw-r--r--
started to save data like positions outside of MapObj & Co
     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 	QString scrolledAttr;
   440 	if ( ((BranchItem*)treeItem)->isScrolled() ) 
   441 		scrolledAttr=attribut ("scrolled","yes");
   442 	else
   443 		scrolledAttr="";
   444 
   445 	// save area, if not scrolled
   446 	QString areaAttr;
   447 	if (!((BranchItem*) (treeItem->parent()) )->isScrolled() )
   448 	{
   449 		areaAttr=
   450 			attribut("x1",QString().setNum(absPos.x()-offset.x())) +
   451 			attribut("y1",QString().setNum(absPos.y()-offset.y())) +
   452 			attribut("x2",QString().setNum(absPos.x()+width()-offset.x())) +
   453 			attribut("y2",QString().setNum(absPos.y()+height()-offset.y()));
   454 
   455 	} else
   456 		areaAttr="";
   457 	
   458 	// Providing an ID for a branch makes export to XHTML easier
   459 	QString idAttr;
   460 	if (treeItem->xlinkCount()>0)
   461 		idAttr=attribut ("id",model->getSelectString(this)); //TODO directly access model
   462 	else
   463 		idAttr="";
   464 
   465     s=beginElement ("branch" 
   466 		+getOrnXMLAttr() 
   467 		+scrolledAttr 
   468 		+areaAttr 
   469 		+idAttr 
   470 		+getIncludeImageAttr() );
   471     incIndent();
   472 
   473 	// save heading
   474     s+=valueElement("heading", treeItem->getHeading(),
   475 		attribut ("textColor",QColor(heading->getColor()).name()));
   476 
   477 	// Save frame
   478 	if (frame->getFrameType()!=FrameObj::NoFrame) 
   479 		s+=frame->saveToDir ();
   480 
   481 	// save names of flags set
   482 	s+=standardFlags->saveToDir(tmpdir,prefix,0);
   483 	
   484 	// Save FloatImages
   485 	for (int i=0; i<floatimage.size(); ++i)
   486 		s+=floatimage.at(i)->saveToDir (tmpdir,prefix);
   487 
   488 	// save note
   489 	if (!treeItem->getNoteObj().isEmpty() )
   490 		s+=treeItem->getNoteObj().saveToDir();
   491 	
   492 	// Save branches
   493 	for (int i=0; i<treeItem->branchCount(); ++i)
   494 		s+=treeItem->getBranchObjNum(i)->saveToDir(tmpdir,prefix,offset);
   495 
   496 	// Save XLinks
   497 	QString ol;	// old link
   498 	QString cl;	// current link
   499 	for (int i=0; i<xlink.size(); ++i)
   500 	{
   501 		cl=xlink.at(i)->saveToDir();
   502 		if (cl!=ol)
   503 		{
   504 			s+=cl;
   505 			ol=cl;
   506 		} else
   507 		{
   508 			qWarning (QString("Ignoring of duplicate xLink in %1").arg(treeItem->getHeading()));
   509 		}
   510 	}	
   511 
   512     decIndent();
   513     s+=endElement   ("branch");
   514     return s;
   515 }
   516 
   517 void BranchObj::addXLink (XLinkObj *xlo)
   518 {
   519 	xlink.append (xlo);
   520 	
   521 }
   522 
   523 void BranchObj::removeXLinkRef (XLinkObj *xlo)
   524 {
   525 	xlink.removeAt (xlink.indexOf(xlo));
   526 }
   527 
   528 void BranchObj::deleteXLink(XLinkObj *xlo)
   529 {
   530 	xlo->deactivate();
   531 	if (!xlo->isUsed()) delete (xlo);
   532 }
   533 
   534 void BranchObj::deleteXLinkAt (int i)
   535 {
   536 	XLinkObj *xlo=xlink.at(i);
   537 	xlo->deactivate();
   538 	if (!xlo->isUsed()) delete(xlo);
   539 }
   540 
   541 XLinkObj* BranchObj::XLinkAt (int i)
   542 {
   543 	return xlink.at(i);
   544 }
   545 
   546 BranchObj* BranchObj::XLinkTargetAt (int i)
   547 {
   548 	if (i>=0 && i<xlink.size())
   549 	{
   550 		if (xlink.at(i))
   551 			return xlink.at(i)->otherBranch (this);
   552 	}
   553 	return NULL;
   554 }
   555 
   556 void BranchObj::setIncludeImagesVer(bool b)
   557 {
   558 	includeImagesVer=b;
   559 	calcBBoxSize();
   560 	positionBBox();
   561 	requestReposition();
   562 }
   563 
   564 bool BranchObj::getIncludeImagesVer()
   565 {
   566 	return includeImagesVer;
   567 }
   568 
   569 void BranchObj::setIncludeImagesHor(bool b)
   570 {
   571 	includeImagesHor=b;
   572 	calcBBoxSize();
   573 	positionBBox();
   574 	requestReposition();
   575 }
   576 
   577 bool BranchObj::getIncludeImagesHor()
   578 {
   579 	return includeImagesHor;
   580 }
   581 
   582 QString BranchObj::getIncludeImageAttr()
   583 {
   584 	QString a;
   585 	if (includeImagesVer)
   586 		a=attribut ("incImgV","true");
   587 	else
   588 		a=attribut ("incImgV","false");
   589 	if (includeImagesHor)
   590 		a+=attribut ("incImgH","true");
   591 	else
   592 		a+=attribut ("incImgH","false");
   593 	return a;	
   594 }
   595 
   596 FloatImageObj* BranchObj::addFloatImage ()
   597 {
   598 	FloatImageObj *newfi=new FloatImageObj (scene,this);
   599 	floatimage.append (newfi);
   600 	if ( ((BranchItem*)treeItem)->hasScrolledParent((BranchItem*)treeItem) )
   601 		newfi->setVisibility (false);
   602 	else	
   603 		newfi->setVisibility(visible);
   604 		/*
   605 	calcBBoxSize();
   606 	positionBBox();
   607 	*/
   608 	requestReposition();
   609 	return newfi;
   610 }
   611 
   612 FloatImageObj* BranchObj::addFloatImage (FloatImageObj *fio)
   613 {
   614 	FloatImageObj *newfi=new FloatImageObj (scene,this);
   615 	floatimage.append (newfi);
   616 	newfi->copy (fio);
   617 	if (((BranchItem*)treeItem)->hasScrolledParent((BranchItem*)treeItem) )
   618 		newfi->setVisibility (false);
   619 	else	
   620 		newfi->setVisibility(visible);
   621 		/*
   622 	calcBBoxSize();
   623 	positionBBox();
   624 	*/
   625 	requestReposition();
   626 	return newfi;
   627 }
   628 
   629 FloatImageObj* BranchObj::getFirstFloatImage ()
   630 {
   631     return floatimage.first();
   632 }
   633 
   634 FloatImageObj* BranchObj::getLastFloatImage ()
   635 {
   636     return floatimage.last();
   637 }
   638 
   639 FloatImageObj* BranchObj::getFloatImageNum (const uint &i)
   640 {
   641     return floatimage.at(i);
   642 }
   643 
   644 void BranchObj::removeFloatImage (FloatImageObj *fio)
   645 {
   646 	int i=floatimage.indexOf (fio);
   647 	if (i>-1) delete (floatimage.takeAt (i));
   648 	calcBBoxSize();
   649 	positionBBox();
   650 	requestReposition();
   651 }
   652 
   653 void BranchObj::savePosInAngle ()
   654 {
   655 	// Save position in angle
   656 	for (int i=0; i<treeItem->branchCount(); ++i)
   657 		treeItem->getBranchObjNum(i)->angle=i;
   658 }
   659 
   660 void BranchObj::setDefAttr (BranchModification mod)
   661 {
   662 	int fontsize;
   663 	switch (treeItem->depth())
   664 	{
   665 		case 0: fontsize=16; break;
   666 		case 1: fontsize=12; break;
   667 		default: fontsize=10; break;
   668 	}	
   669 
   670 	setLinkColor ();
   671 	setLinkStyle(getDefLinkStyle());
   672 	QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
   673 	font.setPointSize(fontsize);
   674 	heading->setFont(font );
   675 
   676 	if (mod==NewBranch)
   677 		setColor (treeItem->getHeadingColor() );
   678 	calcBBoxSize();
   679 }
   680 
   681 void BranchObj::removeBranchHere(BranchObj* borem)	// FIXME-2 getNum no longer available
   682 {
   683 /*
   684 	// This removes the branch bo from list, but 
   685 	// inserts its children at the place of bo
   686 	BranchObj *bo;
   687 	bo=borem->getLastBranch();
   688 	int pos=borem->getNum();
   689 	while (bo)
   690 	{
   691 		bo->linkTo (this,pos+1);
   692 		bo=borem->getLastBranch();
   693 	}	
   694 	removeBranch (borem);
   695 	*/
   696 }
   697 
   698 void BranchObj::removeChildren()	// FIXME-3 not needed here
   699 {
   700 	clear();
   701 }
   702 
   703 void BranchObj::removeBranch(BranchObj* bo)	// FIXME-2 not needed here
   704 {
   705 /*
   706     // if bo is not in branch remove returns false, we
   707     // don't care...
   708 	
   709 	int i=branch.indexOf(bo);
   710     if (i>=0)
   711 	{
   712 		delete (bo);
   713 		branch.removeAt (i);
   714 	} else
   715 		qWarning ("BranchObj::removeBranch tried to remove non existing branch?!\n");
   716 	requestReposition();
   717 	*/
   718 }
   719 
   720 void BranchObj::removeBranchPtr(BranchObj* bo)	// FIXME-3 not needed here
   721 {
   722 /*
   723 	int i=branch.indexOf(bo);
   724 	
   725 	if (i>=0)
   726 		branch.removeAt (i);
   727 	else	
   728 		qWarning ("BranchObj::removeBranchPtr tried to remove non existing branch?!\n");
   729 	requestReposition();
   730 */	
   731 }
   732 
   733 bool BranchObj::canMoveBranchUp() // FIXME-1 move to BranchItem
   734 {
   735 /*
   736 	if (!parObj || depth==1) return false;
   737 	BranchObj* par=(BranchObj*)parObj;
   738 	if (this==par->getTreeItem()->getFirstBranch())
   739 		return false;
   740 	else
   741 		return true;
   742 		*/
   743 return false;
   744 }
   745 
   746 BranchObj* BranchObj::moveBranchUp(BranchObj* bo1) // FIXME-1
   747 {
   748 /*
   749 	savePosInAngle();
   750     int i=branch.indexOf(bo1);
   751     if (i>0) 
   752 	{	// -1 if bo1 not found 
   753 		treeItem->getBranchObjNum(i)->angle--;
   754 		treeItem->getBranchObjNum(i-1)->angle++;
   755 		qSort (branch.begin(),branch.end(), isAbove);
   756 		return treeItem->getBranchObjNum(i);
   757 	} else
   758 */	
   759 		return NULL;
   760 }
   761 
   762 bool BranchObj::canMoveBranchDown() //FIXME-1 move to BranchItem
   763 {
   764 	/* 
   765 	if (!parObj|| depth==1) return false;
   766 	BranchObj* par=(BranchObj*)parObj;
   767 	if (this==par->getTreeItem()->getLastBranch())
   768 		return false;
   769 	else
   770 		return true;
   771 	*/
   772 return false;	
   773 }
   774 
   775 BranchObj* BranchObj::moveBranchDown(BranchObj* bo1)// FIXME-1
   776 {
   777 /*
   778 	savePosInAngle();
   779     int i=branch.indexOf(bo1);
   780 	int j;
   781 	if (i <treeItem->branchCount())
   782 	{
   783 		j = i+1;
   784 		treeItem->getBranchObjNum(i)->angle++;
   785 		treeItem->getBranchObjNum(j)->angle--;
   786 		qSort (branch.begin(),branch.end(), isAbove);
   787 		return treeItem->getBranchObjNum(i);
   788 	} else
   789 */	
   790 		return NULL;
   791 }
   792 
   793 void BranchObj::sortChildren() //FIXME-2  
   794 {
   795 /*
   796 	int childCount=branch.count(); 
   797 	int curChildIndex;
   798 	bool madeChanges=false;
   799 	do
   800 	{
   801 		madeChanges=false;
   802 		for(curChildIndex=1;curChildIndex<childCount;curChildIndex++){
   803 			BranchObj* curChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex);
   804 			BranchObj* prevChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex-1);
   805 			if(prevChild->heading->text().compare(curChild->heading->text())>0)
   806 			{
   807 				this->moveBranchUp(curChild);
   808 				madeChanges=true;
   809 			}
   810 		}
   811 	}while(madeChanges);
   812 */
   813 }
   814 
   815 void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
   816 {
   817 	qreal th = bboxTotal.height();	
   818 	int depth=treeItem->depth();
   819 // TODO testing
   820 /*
   821 
   822 	QString h=QString (depth,' ');
   823 	h+=treeItem->getHeading();
   824 	h+=QString (15,' ');
   825 	h.truncate (15);
   826 	QPointF pp; if (parObj) pp=parObj->getChildPos();
   827 	cout << "BO::alignRelTo ";
   828 	cout<<h.toStdString();
   829 	cout << "    d="<<depth<<
   830 //cout<<  "  ref="<<ref<<
   831       	"  bbox.tL="<<bboxTotal.topLeft()<<
   832 		"  absPos="<<absPos<<
   833 //		"  relPos="<<relPos<<
   834 //		"  parPos="<<pp<<
   835 		"  w="<<bbox.width()<<
   836 		"  h="<<bbox.height()<<
   837 //		"  orient="<<orientation<<
   838 //		"  alignSelf="<<alignSelf<<
   839 //		"  scrolled="<<((BranchItem*)treeItem)->isScrolled()<<
   840 //		"  pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
   841 //		"  hidden="<<hidden<<
   842 		"  th="<<th<<
   843 		endl;
   844 */
   845 
   846 	setOrientation();
   847 	//updateLink();
   848 
   849 	if (depth==1 && parObj)
   850 	{
   851 		// Position relatively, if needed
   852 		//if (useRelPos) move2RelPos (relPos.x(), relPos.y());
   853 
   854 		// Calc angle to mapCenter if I am a mainbranch
   855 		// needed for reordering the mainbranches clockwise 
   856 		// around mapcenter 
   857 		angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ), 
   858 								(int)(y() - parObj->getChildPos().y() ) ) );
   859 	}							
   860 	if (depth>1)
   861     {
   862 		// Align myself depending on orientation and parent, but
   863 		// only if I am not a mainbranch or mapcenter itself
   864 
   865 		if (anim.isAnimated())
   866 		{
   867 			move2RelPos(anim);
   868 		} else
   869 		{
   870 			LinkableMapObj::Orientation o;
   871 			o=parObj->getOrientation();
   872 			if (alignSelf)
   873 				switch (orientation) 
   874 				{
   875 					case LinkableMapObj::LeftOfCenter:
   876 						move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
   877 						//move (ref.x() , ref.y() + (th-bbox.height())/2 );
   878 					break;
   879 					case LinkableMapObj::RightOfCenter:	
   880 						move (ref.x() , ref.y() + (th-bbox.height())/2  );
   881 					break;
   882 					default:
   883 						qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
   884 					break;
   885 			}
   886 		}
   887     }		
   888 
   889 	if ( ((BranchItem*)treeItem)->isScrolled() ) return;
   890 
   891     // Set reference point for alignment of children
   892     QPointF ref2;
   893     if (orientation==LinkableMapObj::LeftOfCenter)
   894 		ref2.setX(bbox.topLeft().x() - linkwidth);
   895     else	
   896 		ref2.setX(bbox.topRight().x() + linkwidth);
   897 
   898 	if (depth==1)
   899 		ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
   900 	else	
   901 		ref2.setY(ref.y() );	
   902 
   903     // Align the children depending on reference point 
   904 	for (int i=0; i<treeItem->branchCount(); ++i)
   905     {	
   906 		if (!treeItem->getBranchNum(i)->isHidden())
   907 		{
   908 			treeItem->getBranchObjNum(i)->alignRelativeTo (ref2,true);
   909 
   910 			// append next branch below current one
   911 			ref2.setY(ref2.y() + treeItem->getBranchObjNum(i)->getBBoxSizeWithChildren().height() );
   912 		}
   913     }
   914 }
   915 
   916 
   917 void BranchObj::reposition()
   918 {	
   919 /* TODO testing only
   920 	if (!treeItem->getHeading().isEmpty())
   921 		cout << "BO::reposition  "<<qPrintable(treeItem->getHeading())<<endl;
   922 	else	
   923 		cout << "BO::reposition  ???"<<endl;
   924 //	cout << "  orient="<<orientation<<endl;
   925 */		
   926 
   927 	if (treeItem->depth()==0)
   928 	{
   929 		// only calculate the sizes once. If the deepest LMO 
   930 		// changes its height,
   931 		// all upper LMOs have to change, too.
   932 		calcBBoxSizeWithChildren();
   933 		updateLink();	// This update is needed if the scene is resized 
   934 						// due to excessive moving of a FIO
   935 
   936 	    alignRelativeTo ( QPointF (absPos.x(),
   937 			absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   938 		//FIXME-2 qSort (branch.begin(),branch.end(), isAbove);
   939 		positionBBox();	// Reposition bbox and contents
   940 	} else
   941 	{
   942 		// This is only important for moving branches:
   943 		// For editing a branch it isn't called...
   944 	    alignRelativeTo ( QPointF (absPos.x(),
   945 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   946 	}
   947 }
   948 
   949 void BranchObj::unsetAllRepositionRequests()
   950 {
   951 	repositionRequest=false;
   952 	for (int i=0; i<treeItem->branchCount(); ++i)
   953 		treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
   954 }
   955 
   956 
   957 QPolygonF BranchObj::shape()
   958 {
   959 	QPolygonF p;
   960 
   961 	QRectF r=getTotalBBox();
   962 	if (orientation==LinkableMapObj::LeftOfCenter)
   963 		p   <<r.bottomLeft()
   964 			<<r.topLeft()
   965 			<<QPointF (bbox.topLeft().x(), r.topLeft().y() )
   966 			<<bbox.topRight()
   967 			<<bbox.bottomRight()
   968 			<<QPointF (bbox.bottomLeft().x(), r.bottomLeft().y() ) ;
   969 	else		
   970 		p   <<r.bottomRight()
   971 			<<r.topRight()
   972 			<<QPointF (bbox.topRight().x(), r.topRight().y() )
   973 			<<bbox.topLeft()
   974 			<<bbox.bottomLeft()
   975 			<<QPointF (bbox.bottomRight().x(), r.bottomRight().y() ) ;
   976 	return p;
   977 }
   978 
   979 QRectF BranchObj::getTotalBBox()
   980 {
   981 	QRectF r=bbox;
   982 
   983 	if ( ((BranchItem*)treeItem)->isScrolled() ) return r;
   984 
   985 	for (int i=0; i<treeItem->branchCount(); ++i)
   986 		if (!treeItem->getBranchNum(i)->isHidden())
   987 			r=addBBox(treeItem->getBranchObjNum(i)->getTotalBBox(),r);
   988 
   989 /* FIXME-3 lots of occurences of treeItem->getBranchObjNum(i) in branchobj.cpp
   990             better check if they are not NULL and maybe simplify...
   991 			(have been NULL at least in calcBBoxSizeWithChilds...)
   992 */			
   993 
   994 /*
   995 	FIXME-1 for (int i=0; i<floatimage.size(); ++i)
   996 		if (!floatimage.at(i)->isHidden())
   997 			r=addBBox(floatimage.at(i)->getTotalBBox(),r);
   998 	*/	
   999 	return r;
  1000 }
  1001 
  1002 QRectF BranchObj::getBBoxSizeWithChildren()
  1003 {
  1004 	return bboxTotal;
  1005 }
  1006 
  1007 void BranchObj::calcBBoxSizeWithChildren()
  1008 {	
  1009 	// This is initially called only from reposition and
  1010 	// and only for mapcenter. So it won't be
  1011 	// called more than once for a single user 
  1012 	// action
  1013 	
  1014 
  1015 	// Calculate size of LMO including all children (to align them later)
  1016 	bboxTotal.setX(bbox.x() );
  1017 	bboxTotal.setY(bbox.y() );
  1018 
  1019 	// if branch is scrolled, ignore children, but still consider floatimages
  1020 	BranchItem *bi=(BranchItem*)treeItem;
  1021 	if ( bi->isScrolled() ) 
  1022 	{
  1023 		bboxTotal.setWidth (bbox.width());
  1024 		bboxTotal.setHeight(bbox.height());
  1025 		return;
  1026 	}
  1027 	
  1028 	if (bi->isHidden())
  1029 	{
  1030 		bboxTotal.setWidth (0);
  1031 		bboxTotal.setHeight(0);
  1032 		if (parObj)
  1033 		{
  1034 			bboxTotal.setX (parObj->x());
  1035 			bboxTotal.setY (parObj->y());
  1036 		} else
  1037 		{
  1038 			bboxTotal.setX (bbox.x());
  1039 			bboxTotal.setY (bbox.y());
  1040 		}
  1041 		return;
  1042 	}
  1043 	
  1044 	QRectF r(0,0,0,0);
  1045 	QRectF br;
  1046 	// Now calculate recursivly
  1047 	// sum of heights 
  1048 	// maximum of widths 
  1049 	// minimum of y
  1050 	for (int i=0; i<treeItem->branchCount(); i++)
  1051 	{
  1052 		if (!bi->getBranchNum(i)->isHidden())
  1053 		{
  1054 			bi->getBranchObjNum(i)->calcBBoxSizeWithChildren();
  1055 			br=bi->getBranchObjNum(i)->getBBoxSizeWithChildren();
  1056 			r.setWidth( max (br.width(), r.width() ));
  1057 			r.setHeight(br.height() + r.height() );
  1058 			if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
  1059 		}
  1060 	}
  1061 	// Add myself and also
  1062 	// add width of link to sum if necessary
  1063 	if (bi->branchCount()<1)
  1064 		bboxTotal.setWidth (bbox.width() + r.width() );
  1065 	else	
  1066 		bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
  1067 	
  1068 	bboxTotal.setHeight(max (r.height(),  bbox.height()));
  1069 }
  1070 
  1071 /*
  1072 void BranchObj::select()	// FIXME-4 try to get rid of this in BO completely
  1073 {
  1074 	cout << "BO::select()\n";
  1075 	textEditor->setText(treeItem->getNoteObj().getNote() );
  1076 	QString fnh=treeItem->getNoteObj().getFilenameHint();
  1077 	if (fnh!="")
  1078 		textEditor->setFilenameHint(treeItem->getNoteObj().getFilenameHint() );
  1079 	else	
  1080 		textEditor->setFilenameHint(getHeading() );
  1081 	textEditor->setFontHint (treeItem->getNoteObj().getFontHint() );
  1082 	//isNoteInEditor=true;
  1083 
  1084 	// set selected and visible
  1085     LinkableMapObj::select();
  1086 
  1087     //if (po)	po->setLastSelectedBranch(this);  needed?
  1088 		
  1089 	// temporary unscroll, if we have scrolled parents somewhere
  1090 	if (parObj) ((BranchObj*)(parObj))->tmpUnscroll();
  1091 
  1092 	//moved to vymmodel or vymview...
  1093 	// Show URL and link in statusbar
  1094 	QString status;
  1095 	if (!url.isEmpty()) status+="URL: "+url+"  ";
  1096 	if (!vymLink.isEmpty()) status+="Link: "+vymLink;
  1097 	if (!status.isEmpty()) mainWindow->statusMessage (status);
  1098 
  1099 	// Update Toolbar
  1100 	updateFlagsToolbar();
  1101 
  1102 	// Update actions
  1103 	model->updateActions();
  1104 }
  1105 	*/
  1106 
  1107 /*
  1108 void BranchObj::unselect()	//FIXME-4 should not be needed
  1109 {
  1110 	cout << "BO::unselect()\n";
  1111 	LinkableMapObj::unselect();
  1112 	// Delete any messages like vymLink in StatusBar
  1113 	mainWindow->statusMessage ("");		//this causes segfault, when MainWindow is already gone in global destructor on quitting vym
  1114 
  1115 	// Save current note
  1116 	if (isNoteInEditor) getNoteFromTextEditor();
  1117 	isNoteInEditor=false;
  1118 
  1119 	// reset temporary unscroll, if we have scrolled parents somewhere
  1120 	if (parObj) ((BranchObj*)(parObj))->resetTmpUnscroll();
  1121 
  1122 	// Erase content of editor 
  1123 	textEditor->setInactive();
  1124 
  1125 	// unselect all buttons in toolbar
  1126 	standardFlagsDefault->updateToolbar();
  1127 }
  1128 */	
  1129 
  1130 QString BranchObj::getSelectString()
  1131 {
  1132 	return model->getSelectString (this);
  1133 }
  1134 
  1135 void BranchObj::setAnimation(const AnimPoint &ap)
  1136 {
  1137 	anim=ap;
  1138 }
  1139 
  1140 bool BranchObj::animate()
  1141 {
  1142 	anim.animate ();
  1143 	if ( anim.isAnimated() )
  1144 	{
  1145 		setRelPos (anim);
  1146 		return true;
  1147 	}
  1148 	parObj->reposition();	// we might have been relinked meanwhile
  1149 	return false;
  1150 }
  1151