initial import
[vym] / branchobj.cpp
diff --git a/branchobj.cpp b/branchobj.cpp
new file mode 100644 (file)
index 0000000..a502d7f
--- /dev/null
@@ -0,0 +1,1629 @@
+#include "branchobj.h"
+
+// #include "texteditor.h"
+#include "geometry.h"
+#include "mapeditor.h"
+#include "mainwindow.h"
+#include "misc.h"
+
+class TextEditor;
+
+extern TextEditor *textEditor;
+extern Main *mainWindow;
+extern FlagRowObj *standardFlagsDefault;
+
+
+/////////////////////////////////////////////////////////////////
+// BranchObj
+/////////////////////////////////////////////////////////////////
+
+BranchObj* BranchObj::itLast=NULL;
+BranchObj* BranchObj::itFirst=NULL;
+
+
+BranchObj::BranchObj () :OrnamentedObj()
+{
+//    cout << "Const BranchObj ()\n";
+    setParObj (this);  
+    init();
+    depth=-1;
+}
+
+BranchObj::BranchObj (QGraphicsScene* s):OrnamentedObj (s)
+{
+//    cout << "Const BranchObj (s)  called from MapCenterObj (s)\n";
+       parObj=NULL;
+    scene=s;
+}
+
+BranchObj::BranchObj (QGraphicsScene* s, LinkableMapObj* p):OrnamentedObj (s)
+{
+//    cout << "Const BranchObj (s,p)\n";
+    scene=s;
+    setParObj (p);     
+    depth=p->getDepth()+1;
+       if (depth==1)
+               // Calc angle to mapCenter if I am a mainbranch
+               // needed for reordering the mainbranches clockwise 
+               // around mapcenter 
+               angle=getAngle (QPointF (x() - parObj->getChildPos().x() , 
+                                                               (y() - parObj->getChildPos().y() ) ) );
+    init();
+}
+
+BranchObj::~BranchObj ()
+{
+       // If I'm animated, I need to un-animate myself first
+       if (anim.isAnimated() )
+       {
+               anim.setAnimated (false);
+               mapEditor->getModel()->stopAnimation (this);
+       }
+
+
+       //cout << "Destr BranchObj of "<<this<<endl;
+       // Check, if this branch was the last child to be deleted
+       // If so, unset the scrolled flags
+
+       BranchObj *po=(BranchObj*)parObj;
+       BranchObj *bo;
+       if (po)
+       {
+               bo=((BranchObj*)parObj)->getLastBranch();
+               if (bo) po->unScroll();
+       }
+       clear();
+}
+
+bool BranchObj::operator< ( const BranchObj & other )
+{
+    return  angle < other.angle;
+}
+
+bool BranchObj::operator== ( const BranchObj & other )
+{
+    return angle == other.angle;
+}
+
+void BranchObj::init () 
+{
+       if (parObj)
+       {
+               absPos=getRandPos();
+               absPos+=parObj->getChildPos();
+       }
+
+    lastSelectedBranch=0;
+
+    setChildObj(this);
+
+       scrolled=false;
+       tmpUnscrolled=false;
+
+       includeImagesVer=false;
+       includeImagesHor=false;
+}
+
+void BranchObj::copy (BranchObj* other)
+{
+    OrnamentedObj::copy(other);
+
+       branch.clear();
+       for (int i=0; i<other->branch.size(); ++i)
+               // Make deep copy of b
+               // Because addBranch again calls copy for the childs,
+               // Those will get a deep copy, too
+               addBranch(other->branch.at(i) );        
+
+       for (int i=0; i<other->floatimage.size(); ++i)
+               addFloatImage  (other->floatimage.at(i));
+       scrolled=other->scrolled;
+       tmpUnscrolled=other->tmpUnscrolled;
+       setVisibility (other->visible);
+
+       angle=other->angle;
+
+    positionBBox();
+}
+
+void BranchObj::clear() 
+{
+       setVisibility (true);
+
+       while (!floatimage.isEmpty())
+               delete floatimage.takeFirst();
+
+       while (!xlink.isEmpty())
+               delete xlink.takeFirst();
+
+       while (!branch.isEmpty())
+               delete branch.takeFirst();
+}
+
+bool isAbove (BranchObj* a, BranchObj *b)
+{
+       if (a->angle < b->angle)
+               return true;
+       else    
+               return false;
+}
+
+int BranchObj::getNum()
+{
+       if (parObj)
+               return ((BranchObj*)parObj)->getNum (this);
+       else
+               return 0;
+}
+
+int BranchObj::getNum(BranchObj *bo)
+{
+       return branch.indexOf (bo);
+}
+
+int BranchObj::getFloatImageNum(FloatImageObj *fio)
+{
+       return floatimage.indexOf(fio);
+}
+
+int BranchObj::countBranches()
+{
+       return branch.count();
+}
+
+int BranchObj::countFloatImages()
+{
+       return floatimage.count();
+}
+
+int BranchObj::countXLinks()
+{
+       return xlink.count();
+}
+
+void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPointF m, int off)
+{
+       // Temporary link to lmo
+       // m is position of mouse pointer 
+       // offset 0: default 1: below lmo   -1 above lmo  (if possible)
+
+
+       BranchObj* o=(BranchObj*)(lmo);
+       if (!parObjTmpBuf) 
+               parObjTmpBuf=parObj;
+
+       // ignore mapcenter and mainbranch
+       if (lmo->getDepth()<2) off=0;
+       if (off==0)
+               link2ParPos=false;
+       else
+               link2ParPos=true;
+       parObj=o;
+
+       depth=parObj->getDepth()+1;
+
+       // setLinkStyle calls updateLink, only set it once
+       if (style!=getDefLinkStyle() ) setLinkStyle (getDefLinkStyle());
+
+       // Move temporary to new position at destination
+       // Usually the positioning would be done by reposition(),
+       // but then also the destination branch would "Jump" around...
+       // Better just do it approximately
+       if (depth==1)
+       {       // new parent is the mapcenter itself
+
+               QPointF p= normalise ( QPointF (m.x() - o->getChildPos().x(),
+                                                                         m.y() - o->getChildPos().y() ));
+               if (p.x()<0) p.setX( p.x()-bbox.width() );
+               move2RelPos (p);
+       } else
+       {       
+               qreal y;
+               if (off==0)
+               {
+                       // new parent is just a branch, link to it
+                       QRectF t=o->getBBoxSizeWithChilds();
+                       if (o->getLastBranch())
+                               y=t.y() + t.height() ;
+                       else
+                               y=t.y();
+
+               } else
+               {
+                       if (off<0)
+                               // we want to link above lmo
+                               y=o->y() - height() + 5;
+                       else    
+                               // we want to link below lmo
+                               // Bottom of sel should be 5 pixels above
+                               // the bottom of the branch _below_ the target:
+                               // Don't try to find that branch, guess 12 pixels
+                               y=o->getChildPos().y()  -height() + 12; 
+               }       
+               if (o->getOrientation()==LinkableMapObj::LeftOfCenter)
+                       move ( o->getChildPos().x() - linkwidth, y );
+               else    
+                       move (o->getChildPos().x() + linkwidth, y );
+       }       
+
+       // updateLink is called implicitly in move
+       requestReposition();    
+}
+
+void BranchObj::unsetParObjTmp()
+{
+       if (parObjTmpBuf) 
+       {
+               link2ParPos=false;
+               parObj=parObjTmpBuf;
+               parObjTmpBuf=NULL;
+               depth=parObj->getDepth()+1;
+               setLinkStyle (getDefLinkStyle() );
+               updateLink();
+       }               
+}
+
+void BranchObj::unScroll()
+{
+       if (tmpUnscrolled) resetTmpUnscroll();
+       if (scrolled) toggleScroll();
+}
+
+void BranchObj::toggleScroll()
+{
+       if (scrolled)
+       {
+               scrolled=false;
+               systemFlags->deactivate("scrolledright");
+               for (int i=0; i<branch.size(); ++i)
+                       branch.at(i)->setVisibility(true);
+       } else
+       {
+               scrolled=true;
+               systemFlags->activate("scrolledright");
+               for (int i=0; i<branch.size(); ++i)
+                       branch.at(i)->setVisibility(false);
+       }
+       calcBBoxSize();
+       positionBBox(); 
+       move (absPos.x(), absPos.y() );
+       forceReposition();
+}
+
+bool BranchObj::isScrolled()
+{
+       return scrolled;
+}
+
+bool BranchObj::hasScrolledParent(BranchObj *start)
+{
+       // Calls parents recursivly to
+       // find out, if we are scrolled at all.
+       // But ignore myself, just look at parents.
+
+       if (this !=start && scrolled) return true;
+
+       BranchObj* bo=(BranchObj*)(parObj);
+       if (bo) 
+               return bo->hasScrolledParent(start);
+       else
+               return false;
+}
+
+void BranchObj::tmpUnscroll()
+{
+       // Unscroll parent (recursivly)
+       BranchObj* bo=(BranchObj*)(parObj);
+       if (bo) bo->tmpUnscroll();
+               
+       // Unscroll myself
+       if (scrolled)
+       {
+               tmpUnscrolled=true;
+               systemFlags->activate("tmpUnscrolledright");
+               toggleScroll();
+       }       
+}
+
+void BranchObj::resetTmpUnscroll()
+{
+       // Unscroll parent (recursivly)
+       BranchObj* bo=(BranchObj*)(parObj);
+       if (bo)
+               bo->resetTmpUnscroll();
+               
+       // Unscroll myself
+       if (tmpUnscrolled)
+       {
+               tmpUnscrolled=false;
+               systemFlags->deactivate("tmpUnscrolledright");
+               toggleScroll();
+       }       
+}
+
+void BranchObj::setVisibility(bool v, int toDepth)
+{
+    if (depth <= toDepth)
+    {
+               frame->setVisibility(v);
+               heading->setVisibility(v);
+               systemFlags->setVisibility(v);
+               standardFlags->setVisibility(v);
+               LinkableMapObj::setVisibility (v);
+               
+               // Only change childs, if I am not scrolled
+               if (!scrolled && (depth < toDepth))
+               {
+                       // Now go recursivly through all childs
+                       int i;
+                       for (i=0; i<branch.size(); ++i)
+                               branch.at(i)->setVisibility (v,toDepth);        
+                       for (i=0; i<floatimage.size(); ++i)
+                               floatimage.at(i)->setVisibility (v);
+                       for (i=0; i<xlink.size(); ++i)  
+                               xlink.at(i)->setVisibility ();  
+               }
+    } // depth <= toDepth      
+       requestReposition();
+}      
+
+void BranchObj::setVisibility(bool v)
+{
+    setVisibility (v,MAX_DEPTH);
+}
+
+
+void BranchObj::setLinkColor ()
+{
+       // Overloaded from LinkableMapObj
+       // BranchObj can use color of heading
+
+       if (mapEditor)
+       {
+               if (mapEditor->getMapLinkColorHint()==HeadingColor)
+                       LinkableMapObj::setLinkColor (heading->getColor() );
+               else    
+                       LinkableMapObj::setLinkColor ();
+       }               
+}
+
+void BranchObj::setColorSubtree(QColor col)
+{
+       setColor (col);
+       for (int i=0; i<branch.size(); ++i)
+               branch.at(i)->setColorSubtree(col);
+}
+
+BranchObj* BranchObj::first()
+{
+       itLast=NULL;    
+       itFirst=this;
+       return this; 
+}
+       
+BranchObj* BranchObj::next()
+{
+       BranchObj *bo;
+       BranchObj *lmo;
+       BranchObj *po=(BranchObj*)parObj;
+
+       if (branch.isEmpty())
+               bo=NULL;
+       else
+               bo=branch.first();
+
+       if (!itLast)
+       {
+               // no itLast, we are just beginning
+               if (bo) 
+               {
+                       // we have childs, return first one
+                       itLast=this;
+                       return bo;
+               }       
+               else
+               {
+                       // No childs, so there is no next
+                       itLast=this;
+                       return NULL;
+               }       
+       }
+
+       // We have an itLast
+       if (itLast==po)
+       {       // We come from parent
+               if (bo)
+               {
+                       // there are childs, go there
+                       itLast=this;
+                       return bo;
+               }       
+               else
+               {       // no childs, try to go up again
+                       if (po)
+                       {
+                               // go back to parent and try to find next there
+                               itLast=this;
+                               lmo=po->next();
+                               itLast=this;
+                               return lmo;
+
+                       }       
+                       else
+                       {
+                               // can't go up, I am mapCenter, no next
+                               itLast=NULL;
+                               return NULL;
+                       }       
+               }
+       }
+
+       // We don't come from parent, but from brother or childs
+
+       // Try to find last child, where we came from, in my own childs
+       bool searching=true;
+       int i=0;
+       while (i<branch.size())
+       {
+               // Try to find itLast in my own childs
+               if (itLast==branch.at(i))
+               {
+                       // ok, we come from my own childs
+                       if (i<branch.size()-1)
+                               bo=branch.at(i+1);
+                        else
+                               bo=NULL;
+                       searching=false;
+                       i=branch.size();
+               }       
+               ++i;    
+       }
+       if (!searching)
+       {       // found itLast in my childs
+               if (bo)
+               {
+                       // found a brother of lastLMO 
+                       itLast=this;
+                       return bo;
+               }       
+               else
+               {
+                       if (po)
+                       {
+                               if (this==itFirst) return NULL; // Stop at starting point
+                               // go up
+                               itLast=this;
+                               lmo=po->next();
+                               itLast=this;
+                               return lmo;
+                       }
+                       else
+                       {
+                               // can't go up, I am mapCenter
+                               itLast=NULL;
+                               return NULL;
+                       }       
+               }
+       }
+
+       // couldn't find last child, it must be a nephew of mine
+       if (branch.size()>0)
+       {
+               // proceed with my first child
+               itLast=this;    
+               return branch.first();
+       }       
+       else
+       {
+               // or go back to my parents
+               if (po)
+               {
+                       // go up
+                       itLast=this;
+                       lmo=po->next();
+                       itLast=this;
+                       return lmo;
+               }       
+               else
+               {
+                       // can't go up, I am mapCenter
+                       itLast=NULL;
+                       return NULL;
+               }       
+       }       
+}
+
+BranchObj* BranchObj::getLastIterator()
+{
+       return itLast;
+}
+
+void BranchObj::setLastIterator(BranchObj* it)
+{
+       itLast=it;
+}
+
+void BranchObj::positionContents()
+{
+    for (int i=0; i<floatimage.size(); ++i )
+               floatimage.at(i)->reposition();
+       OrnamentedObj::positionContents();
+}
+
+void BranchObj::move (double x, double y)
+{
+       OrnamentedObj::move (x,y);
+    for (int i=0; i<floatimage.size(); ++i )
+               floatimage.at(i)->reposition();
+    positionBBox();
+}
+
+void BranchObj::move (QPointF p)
+{
+       move (p.x(), p.y());
+}
+
+void BranchObj::moveBy (double x, double y)
+{
+       OrnamentedObj::moveBy (x,y);
+       for (int i=0; i<branch.size(); ++i)
+               branch.at(i)->moveBy (x,y);
+    positionBBox();
+}
+       
+void BranchObj::moveBy (QPointF p)
+{
+       moveBy (p.x(), p.y());
+}
+
+
+void BranchObj::positionBBox()
+{
+       QPointF ap=getAbsPos();
+       bbox.moveTopLeft (ap);
+       positionContents();
+
+       // set the frame
+       frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
+
+       // Update links to other branches
+       for (int i=0; i<xlink.size(); ++i)
+               xlink.at(i)->updateXLink();
+}
+
+void BranchObj::calcBBoxSize()
+{
+    QSizeF heading_r=heading->getSize();
+    qreal heading_w=(qreal) heading_r.width() ;
+    qreal heading_h=(qreal) heading_r.height() ;
+    QSizeF sysflags_r=systemFlags->getSize();
+       qreal sysflags_h=sysflags_r.height();
+       qreal sysflags_w=sysflags_r.width();
+    QSizeF stanflags_r=standardFlags->getSize();
+       qreal stanflags_h=stanflags_r.height();
+       qreal stanflags_w=stanflags_r.width();
+    qreal w;
+    qreal h;
+
+       // set width to sum of all widths
+       w=heading_w + sysflags_w + stanflags_w;
+       // set height to maximum needed height
+       h=max (sysflags_h,stanflags_h);
+       h=max (h,heading_h);
+
+       // Save the dimension of flags and heading
+       ornamentsBBox.setSize ( QSizeF(w,h));
+
+       // clickBox includes Flags and Heading
+    clickBox.setSize (ornamentsBBox.size() );
+
+       // Floatimages 
+       QPointF rp;
+
+       topPad=botPad=leftPad=rightPad=0;
+       if (includeImagesVer || includeImagesHor)
+       {
+               if (countFloatImages()>0)
+               {
+                       for (int i=0; i<floatimage.size(); ++i )
+                       {
+                               rp=floatimage.at(i)->getRelPos();
+                               if (includeImagesVer)
+                               {
+                                       if (rp.y() < 0) 
+                                               topPad=max (topPad,-rp.y()-h);
+                                       if (rp.y()+floatimage.at(i)->height() > 0)
+                                               botPad=max (botPad,rp.y()+floatimage.at(i)->height());
+                               }               
+                               if (includeImagesHor)
+                               {
+                                       if (orientation==LinkableMapObj::RightOfCenter)
+                                       {
+                                               if (-rp.x()-w > 0) 
+                                                       leftPad=max (leftPad,-rp.x()-w);
+                                               if (rp.x()+floatimage.at(i)->width() > 0)
+                                                       rightPad=max (rightPad,rp.x()+floatimage.at(i)->width());
+                                       } else
+                                       {
+                                               if (rp.x()< 0) 
+                                                       leftPad=max (leftPad,-rp.x());
+                                               if (rp.x()+floatimage.at(i)->width() > w)
+                                                       rightPad=max (rightPad,rp.x()+floatimage.at(i)->width()-w);
+                                       }
+                               }               
+                       }       
+               }       
+               h+=topPad+botPad;
+               w+=leftPad+rightPad;
+       }
+
+       // Frame thickness
+    w+=frame->getPadding();
+    h+=frame->getPadding();
+       
+       // Finally set size
+    bbox.setSize (QSizeF (w,h));
+}
+
+void BranchObj::setDockPos()
+{
+       // Sets childpos and parpos depending on orientation
+       if (getOrientation()==LinkableMapObj::LeftOfCenter )
+    {
+               childPos=QPointF (
+                       ornamentsBBox.bottomLeft().x(), 
+                       bottomlineY);
+               parPos=QPointF (
+                       ornamentsBBox.bottomRight().x(),
+                       bottomlineY);
+    } else
+    {
+               childPos=QPointF (
+                       ornamentsBBox.bottomRight().x(), 
+                       bottomlineY);
+               parPos=QPointF (
+                       ornamentsBBox.bottomLeft().x(),
+                       bottomlineY);
+    }
+}
+
+LinkableMapObj* BranchObj::findMapObj(QPointF p, LinkableMapObj* excludeLMO)
+{
+       // Search branches
+    LinkableMapObj *lmo;
+       for (int i=0; i<branch.size(); ++i)
+    {  
+               lmo=branch.at(i)->findMapObj(p, excludeLMO);
+               if (lmo != NULL) return lmo;
+    }
+       
+
+       // Search myself
+    if (inBox (p,clickBox) && (this != excludeLMO) && isVisibleObj() ) 
+               return this;
+
+       // Search float images
+    for (int i=0; i<floatimage.size(); ++i )
+               if (inBox(p,floatimage.at(i)->getClickBox()) && 
+                       (floatimage.at(i) != excludeLMO) && 
+                       floatimage.at(i)->getParObj()!= excludeLMO &&
+                       floatimage.at(i)->isVisibleObj() 
+               ) return floatimage.at(i);
+
+    return NULL;
+}
+
+LinkableMapObj* BranchObj::findID (QString sid)
+{
+       // Search branches
+    LinkableMapObj *lmo;
+       for (int i=0; i<branch.size(); ++i)
+    {  
+               lmo=branch.at(i)->findID (sid);
+               if (lmo != NULL) return lmo;
+    }
+       
+       // Search myself
+       if (sid==objID) return this;
+
+
+/*
+       // Search float images
+    for (int i=0; i<floatimage.size(); ++i )
+               if (floatimage.at(i)->inBox(p) && 
+                       (floatimage.at(i) != excludeLMO) && 
+                       floatimage.at(i)->getParObj()!= excludeLMO &&
+                       floatimage.at(i)->isVisibleObj() 
+               ) return floatimage.at(i);
+*/
+    return NULL;
+}
+
+void BranchObj::setHeading(QString s)
+{
+    heading->setText(s);       // set new heading
+       calcBBoxSize();                 // recalculate bbox
+    positionBBox();                    // rearrange contents
+       requestReposition();
+}
+
+void BranchObj::setHideTmp (HideTmpMode mode)
+{
+       if (mode==HideExport && (hideExport|| hasHiddenExportParent() ) )
+       {
+               // Hide stuff according to hideExport flag and parents
+               setVisibility (false);
+               hidden=true;
+       }else
+       {
+               // Do not hide, but still take care of scrolled status
+               if (hasScrolledParent(this))
+                       setVisibility (false);
+               else
+                       setVisibility (true);
+               hidden=false;
+       }       
+
+       // And take care of my childs
+       for (int i=0; i<branch.size(); ++i)
+               branch.at(i)->setHideTmp (mode);
+}
+
+bool BranchObj::hasHiddenExportParent()
+{
+       // Calls parents recursivly to
+       // find out, if we or parents are temp. hidden
+
+       if (hidden || hideExport) return true;
+
+       BranchObj* bo=(BranchObj*)parObj;
+       if (bo) 
+               return bo->hasHiddenExportParent();
+       else
+               return false;
+}
+
+QString BranchObj::saveToDir (const QString &tmpdir,const QString &prefix, const QPointF& offset)
+{
+       // Cloudy stuff can be hidden during exports
+       if (hidden) return "";
+
+       // Update of note is usually done while unselecting a branch
+       if (isNoteInEditor) getNoteFromTextEditor();
+       
+    QString s,a;
+       QString scrolledAttr;
+       if (scrolled) 
+               scrolledAttr=attribut ("scrolled","yes");
+       else
+               scrolledAttr="";
+
+       // save area, if not scrolled
+       QString areaAttr;
+       if (!((BranchObj*)(parObj))->isScrolled() )
+       {
+               areaAttr=
+                       attribut("x1",QString().setNum(absPos.x()-offset.x())) +
+                       attribut("y1",QString().setNum(absPos.y()-offset.y())) +
+                       attribut("x2",QString().setNum(absPos.x()+width()-offset.x())) +
+                       attribut("y2",QString().setNum(absPos.y()+height()-offset.y()));
+
+       } else
+               areaAttr="";
+       
+       // Providing an ID for a branch makes export to XHTML easier
+       QString idAttr;
+       if (countXLinks()>0)
+               idAttr=attribut ("id",mapEditor->getModel()->getSelectString(this)); //TODO directly access model
+       else
+               idAttr="";
+
+    s=beginElement ("branch" 
+               +getOrnXMLAttr() 
+               +scrolledAttr 
+               +areaAttr 
+               +idAttr 
+               +getIncludeImageAttr() );
+    incIndent();
+
+       // save heading
+    s+=valueElement("heading", getHeading(),
+               attribut ("textColor",QColor(heading->getColor()).name()));
+
+       // Save frame
+       if (frame->getFrameType()!=FrameObj::NoFrame) 
+               s+=frame->saveToDir ();
+
+       // save names of flags set
+       s+=standardFlags->saveToDir(tmpdir,prefix,0);
+       
+       // Save FloatImages
+       for (int i=0; i<floatimage.size(); ++i)
+               s+=floatimage.at(i)->saveToDir (tmpdir,prefix);
+
+       // save note
+       if (!note.isEmpty() )
+               s+=note.saveToDir();
+       
+       // Save branches
+       for (int i=0; i<branch.size(); ++i)
+               s+=branch.at(i)->saveToDir(tmpdir,prefix,offset);
+
+       // Save XLinks
+       QString ol;     // old link
+       QString cl;     // current link
+       for (int i=0; i<xlink.size(); ++i)
+       {
+               cl=xlink.at(i)->saveToDir();
+               if (cl!=ol)
+               {
+                       s+=cl;
+                       ol=cl;
+               } else
+               {
+                       qWarning (QString("Ignoring of duplicate xLink in %1").arg(getHeading()));
+               }
+       }       
+
+    decIndent();
+    s+=endElement   ("branch");
+    return s;
+}
+
+void BranchObj::addXLink (XLinkObj *xlo)
+{
+       xlink.append (xlo);
+       
+}
+
+void BranchObj::removeXLinkRef (XLinkObj *xlo)
+{
+       xlink.removeAt (xlink.indexOf(xlo));
+}
+
+void BranchObj::deleteXLink(XLinkObj *xlo)
+{
+       xlo->deactivate();
+       if (!xlo->isUsed()) delete (xlo);
+}
+
+void BranchObj::deleteXLinkAt (int i)
+{
+       XLinkObj *xlo=xlink.at(i);
+       xlo->deactivate();
+       if (!xlo->isUsed()) delete(xlo);
+}
+
+XLinkObj* BranchObj::XLinkAt (int i)
+{
+       return xlink.at(i);
+}
+
+int BranchObj::countXLink()
+{
+       return xlink.count();
+}
+
+
+BranchObj* BranchObj::XLinkTargetAt (int i)
+{
+       if (i>=0 && i<xlink.size())
+       {
+               if (xlink.at(i))
+                       return xlink.at(i)->otherBranch (this);
+       }
+       return NULL;
+}
+
+void BranchObj::setIncludeImagesVer(bool b)
+{
+       includeImagesVer=b;
+       calcBBoxSize();
+       positionBBox();
+       requestReposition();
+}
+
+bool BranchObj::getIncludeImagesVer()
+{
+       return includeImagesVer;
+}
+
+void BranchObj::setIncludeImagesHor(bool b)
+{
+       includeImagesHor=b;
+       calcBBoxSize();
+       positionBBox();
+       requestReposition();
+}
+
+bool BranchObj::getIncludeImagesHor()
+{
+       return includeImagesHor;
+}
+
+QString BranchObj::getIncludeImageAttr()
+{
+       QString a;
+       if (includeImagesVer)
+               a=attribut ("incImgV","true");
+       else
+               a=attribut ("incImgV","false");
+       if (includeImagesHor)
+               a+=attribut ("incImgH","true");
+       else
+               a+=attribut ("incImgH","false");
+       return a;       
+}
+
+FloatImageObj* BranchObj::addFloatImage ()
+{
+       FloatImageObj *newfi=new FloatImageObj (scene,this);
+       floatimage.append (newfi);
+       if (hasScrolledParent(this) )
+               newfi->setVisibility (false);
+       else    
+               newfi->setVisibility(visible);
+               /*
+       calcBBoxSize();
+       positionBBox();
+       */
+       requestReposition();
+       return newfi;
+}
+
+FloatImageObj* BranchObj::addFloatImage (FloatImageObj *fio)
+{
+       FloatImageObj *newfi=new FloatImageObj (scene,this);
+       floatimage.append (newfi);
+       newfi->copy (fio);
+       if (hasScrolledParent(this) )
+               newfi->setVisibility (false);
+       else    
+               newfi->setVisibility(visible);
+               /*
+       calcBBoxSize();
+       positionBBox();
+       */
+       requestReposition();
+       return newfi;
+}
+
+FloatImageObj* BranchObj::getFirstFloatImage ()
+{
+    return floatimage.first();
+}
+
+FloatImageObj* BranchObj::getLastFloatImage ()
+{
+    return floatimage.last();
+}
+
+FloatImageObj* BranchObj::getFloatImageNum (const uint &i)
+{
+    return floatimage.at(i);
+}
+
+void BranchObj::removeFloatImage (FloatImageObj *fio)
+{
+       int i=floatimage.indexOf (fio);
+       if (i>-1) delete (floatimage.takeAt (i));
+       calcBBoxSize();
+       positionBBox();
+       requestReposition();
+}
+
+void BranchObj::savePosInAngle ()
+{
+       // Save position in angle
+       for (int i=0; i<branch.size(); ++i)
+               branch.at(i)->angle=i;
+}
+
+void BranchObj::setDefAttr (BranchModification mod)
+{
+       int fontsize;
+       switch (depth)
+       {
+               case 0: fontsize=16; break;
+               case 1: fontsize=12; break;
+               default: fontsize=10; break;
+       }       
+
+       setLinkColor ();
+       setLinkStyle(getDefLinkStyle());
+       QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
+       font.setPointSize(fontsize);
+       heading->setFont(font );
+
+       if (mod==NewBranch)
+               setColor (((BranchObj*)(parObj))->getColor());
+       
+       calcBBoxSize();
+}
+
+BranchObj* BranchObj::addBranch()
+{
+    BranchObj* newbo=new BranchObj(scene,this);
+    branch.append (newbo);
+    newbo->setParObj(this);
+       newbo->setDefAttr(NewBranch);
+    newbo->setHeading ("new");
+       if (scrolled)
+               newbo->setVisibility (false);
+       else    
+               newbo->setVisibility(visible);
+       newbo->updateLink();    
+       requestReposition();
+       return newbo;
+}
+
+BranchObj* BranchObj::addBranch(BranchObj* bo)
+{
+    BranchObj* newbo=new BranchObj(scene,this);
+    branch.append (newbo);
+    newbo->copy(bo);
+    newbo->setParObj(this);
+       newbo->setDefAttr(MovedBranch);
+       if (scrolled)
+               newbo->setVisibility (false);
+       else    
+               newbo->setVisibility(bo->visible);
+       newbo->updateLink();    
+       requestReposition();
+       return newbo;
+}
+
+BranchObj* BranchObj::addBranchPtr(BranchObj* bo)
+{
+       branch.append (bo);
+       bo->setParObj (this);
+       bo->depth=depth+1;
+       bo->setDefAttr(MovedBranch);
+       if (scrolled) tmpUnscroll();
+       setLastSelectedBranch (bo);
+       return bo;
+}
+
+BranchObj* BranchObj::insertBranch(int pos)
+{
+       savePosInAngle();
+       // Add new bo and resort branches
+       BranchObj *newbo=addBranch ();
+       newbo->angle=pos-0.5;
+       qSort (branch.begin(),branch.end(), isAbove);
+       return newbo;
+}
+
+BranchObj* BranchObj::insertBranch(BranchObj* bo, int pos)
+{
+       savePosInAngle();
+       // Add new bo and resort branches
+       bo->angle=pos-0.5;
+       BranchObj *newbo=addBranch (bo);
+       qSort (branch.begin(),branch.end(), isAbove);
+       return newbo;
+}
+
+BranchObj* BranchObj::insertBranchPtr (BranchObj* bo, int pos)
+{
+       savePosInAngle();
+       // Add new bo and resort branches
+       bo->angle=pos-0.5;
+       branch.append (bo);
+       bo->setParObj (this);
+       bo->depth=depth+1;
+       bo->setDefAttr (MovedBranch);
+       if (scrolled) tmpUnscroll();
+       setLastSelectedBranch (bo);
+       qSort (branch.begin(),branch.end(), isAbove);
+       return bo;
+}
+
+void BranchObj::removeBranchHere(BranchObj* borem)
+{
+       // This removes the branch bo from list, but 
+       // inserts its childs at the place of bo
+       BranchObj *bo;
+       bo=borem->getLastBranch();
+       int pos=borem->getNum();
+       while (bo)
+       {
+               bo->linkTo (this,pos+1);
+               bo=borem->getLastBranch();
+       }       
+       removeBranch (borem);
+}
+
+void BranchObj::removeChilds()
+{
+       clear();
+}
+
+void BranchObj::removeBranch(BranchObj* bo)
+{
+    // if bo is not in branch remove returns false, we
+    // don't care...
+       
+       int i=branch.indexOf(bo);
+    if (i>=0)
+       {
+               delete (bo);
+               branch.removeAt (i);
+       } else
+               qWarning ("BranchObj::removeBranch tried to remove non existing branch?!\n");
+       requestReposition();
+}
+
+void BranchObj::removeBranchPtr(BranchObj* bo)
+{
+       int i=branch.indexOf(bo);
+       
+       if (i>=0)
+               branch.removeAt (i);
+       else    
+               qWarning ("BranchObj::removeBranchPtr tried to remove non existing branch?!\n");
+       requestReposition();
+}
+
+void BranchObj::setLastSelectedBranch (BranchObj* bo)
+{
+    lastSelectedBranch=branch.indexOf(bo);
+}
+
+BranchObj* BranchObj::getLastSelectedBranch ()
+{
+    if (lastSelectedBranch>=0)
+       {
+               if ( branch.size()>lastSelectedBranch) 
+                       return branch.at(lastSelectedBranch);
+               if (branch.size()>0)
+                       return branch.last();
+       }       
+    return NULL;
+}
+
+BranchObj* BranchObj::getFirstBranch ()
+{
+       if (branch.size()>0)
+               return branch.first();
+       else
+               return NULL;
+}
+
+BranchObj* BranchObj::getLastBranch ()
+{
+       if (branch.size()>0)
+               return branch.last();
+       else
+               return NULL;
+}
+
+BranchObj* BranchObj::getBranchNum (int i)
+{
+       if (i>=0 && i<branch.size())
+               return branch.at(i);
+       else    
+               return  NULL;
+}
+
+bool BranchObj::canMoveBranchUp() 
+{
+       if (!parObj || depth==1) return false;
+       BranchObj* par=(BranchObj*)parObj;
+       if (this==par->getFirstBranch())
+               return false;
+       else
+               return true;
+}
+
+BranchObj* BranchObj::moveBranchUp(BranchObj* bo1) // modify my childlist
+{
+       savePosInAngle();
+    int i=branch.indexOf(bo1);
+    if (i>0) 
+       {       // -1 if bo1 not found 
+               branch.at(i)->angle--;
+               branch.at(i-1)->angle++;
+               qSort (branch.begin(),branch.end(), isAbove);
+               return branch.at(i);
+       } else
+               return NULL;
+}
+
+bool BranchObj::canMoveBranchDown() 
+{
+       if (!parObj|| depth==1) return false;
+       BranchObj* par=(BranchObj*)parObj;
+       if (this==par->getLastBranch())
+               return false;
+       else
+               return true;
+}
+
+BranchObj* BranchObj::moveBranchDown(BranchObj* bo1)// modify my childlist
+{
+       savePosInAngle();
+    int i=branch.indexOf(bo1);
+       int j;
+       if (i <branch.size())
+       {
+               j = i+1;
+               branch.at(i)->angle++;
+               branch.at(j)->angle--;
+               qSort (branch.begin(),branch.end(), isAbove);
+               return branch.at(i);
+       } else
+               return NULL;
+}
+
+void BranchObj::sortChildren()
+{
+       int childCount=branch.count();
+       int curChildIndex;
+       bool madeChanges=false;
+       do
+       {
+               madeChanges=false;
+               for(curChildIndex=1;curChildIndex<childCount;curChildIndex++){
+                       BranchObj* curChild=(BranchObj*)branch.at(curChildIndex);
+                       BranchObj* prevChild=(BranchObj*)branch.at(curChildIndex-1);
+                       if(prevChild->heading->text().compare(curChild->heading->text())>0)
+                       {
+                               this->moveBranchUp(curChild);
+                               madeChanges=true;
+                       }
+               }
+       }while(madeChanges);
+}
+
+
+BranchObj* BranchObj::linkTo (BranchObj* dst, int pos)
+{
+       // Find current parent and 
+       // remove pointer to myself there
+       if (!dst) return NULL;
+       BranchObj *par=(BranchObj*)parObj;
+       if (par)
+               par->removeBranchPtr (this);
+       else
+               return NULL;
+
+       // Create new pointer to myself at dst
+       if (pos<0||dst->getDepth()==0)
+       {       
+               // links myself as last branch at dst
+               dst->addBranchPtr (this);
+               updateLink();
+               return this;
+       } else
+       {
+               // inserts me at pos in parent of dst
+               if (par)
+               {
+                       BranchObj *bo=dst->insertBranchPtr (this,pos);
+                       bo->setDefAttr(MovedBranch);
+                       updateLink();
+                       return bo;
+
+               } else
+                       return NULL;
+       }       
+}
+
+void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
+{
+       qreal th = bboxTotal.height();  
+// TODO testing
+/*
+       QPointF pp; if (parObj) pp=parObj->getChildPos();
+       cout << "BO::alignRelTo "<<qPrintable (getHeading());
+       cout << "    d="<<depth<<
+               "  ref="<<ref<<
+//             "  bbox.topLeft="<<bboxTotal.topLeft()<<
+               "  absPos="<<absPos<<
+               "  relPos="<<relPos<<
+               "  parPos="<<pp<<
+               "  orient="<<orientation<<
+//             "  pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
+//             "  hidden="<<hidden<<
+//             "  th="<<th<<
+               endl;
+*/
+
+       setOrientation();
+       //updateLink();
+
+       if (depth<2)
+       {
+               if (depth==1)
+               {
+                       // Position relatively, if needed
+                       //if (useRelPos) move2RelPos (relPos.x(), relPos.y());
+
+                       // Calc angle to mapCenter if I am a mainbranch
+                       // needed for reordering the mainbranches clockwise 
+                       // around mapcenter 
+                       angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ), 
+                                                                       (int)(y() - parObj->getChildPos().y() ) ) );
+               }                                                       
+       } 
+       else
+    {
+               // Align myself depending on orientation and parent, but
+               // only if I am not a mainbranch or mapcenter itself
+
+               if (anim.isAnimated())
+               {
+                       move2RelPos(anim);
+               } else
+               {
+                       LinkableMapObj::Orientation o;
+                       o=parObj->getOrientation();
+                       if (alignSelf)
+                               switch (orientation) 
+                               {
+                                       case LinkableMapObj::LeftOfCenter:
+                                               move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
+                                       break;
+                                       case LinkableMapObj::RightOfCenter:     
+                                               move (ref.x() , ref.y() + (th-bbox.height())/2  );
+                                       break;
+                                       default:
+                                               qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
+                                       break;
+                               }       
+               }
+    }          
+
+       if (scrolled) return;
+
+    // Set reference point for alignment of childs
+    QPointF ref2;
+    if (orientation==LinkableMapObj::LeftOfCenter)
+               ref2.setX(bbox.topLeft().x() - linkwidth);
+    else       
+               ref2.setX(bbox.topRight().x() + linkwidth);
+
+       if (depth==1)
+               ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
+       else    
+               ref2.setY(ref.y() );    
+
+    // Align the childs depending on reference point 
+       for (int i=0; i<branch.size(); ++i)
+    {  
+               if (!branch.at(i)->isHidden())
+               {
+                       branch.at(i)->alignRelativeTo (ref2,true);
+                       ref2.setY(ref2.y() + branch.at(i)->getBBoxSizeWithChilds().height() );
+               }
+    }
+}
+
+
+void BranchObj::reposition()
+{      
+/* TODO testing only
+       if (!getHeading().isEmpty())
+               cout << "BO::reposition  "<<qPrintable(getHeading())<<endl;
+       else    
+               cout << "BO::reposition  ???"<<endl;
+
+       cout << "  orient="<<orientation<<endl;
+*/             
+
+       if (depth==0)
+       {
+               // only calculate the sizes once. If the deepest LMO 
+               // changes its height,
+               // all upper LMOs have to change, too.
+               calcBBoxSizeWithChilds();
+               updateLink();   // This update is needed if the scene is resized 
+                                               // due to excessive moving of a FIO
+
+           alignRelativeTo ( QPointF (absPos.x(),
+                       absPos.y()-(bboxTotal.height()-bbox.height())/2) );
+               qSort (branch.begin(),branch.end(), isAbove);
+               positionBBox(); // Reposition bbox and contents
+       } else
+       {
+               // This is only important for moving branches:
+               // For editing a branch it isn't called...
+           alignRelativeTo ( QPointF (absPos.x(),
+                                                       absPos.y()-(bboxTotal.height()-bbox.height())/2) );
+       }
+}
+
+void BranchObj::unsetAllRepositionRequests()
+{
+       repositionRequest=false;
+       for (int i=0; i<branch.size(); ++i)
+               branch.at(i)->unsetAllRepositionRequests();
+}
+
+
+QPolygonF BranchObj::shape()
+{
+       QPolygonF p;
+
+       QRectF r=getTotalBBox();
+       if (orientation==LinkableMapObj::LeftOfCenter)
+               p   <<r.bottomLeft()
+                       <<r.topLeft()
+                       <<QPointF (bbox.topLeft().x(), r.topLeft().y() )
+                       <<bbox.topRight()
+                       <<bbox.bottomRight()
+                       <<QPointF (bbox.bottomLeft().x(), r.bottomLeft().y() ) ;
+       else            
+               p   <<r.bottomRight()
+                       <<r.topRight()
+                       <<QPointF (bbox.topRight().x(), r.topRight().y() )
+                       <<bbox.topLeft()
+                       <<bbox.bottomLeft()
+                       <<QPointF (bbox.bottomRight().x(), r.bottomRight().y() ) ;
+       return p;
+}
+
+QRectF BranchObj::getTotalBBox()
+{
+       QRectF r=bbox;
+
+       if (scrolled) return r;
+
+       for (int i=0; i<branch.size(); ++i)
+               if (!branch.at(i)->isHidden())
+                       r=addBBox(branch.at(i)->getTotalBBox(),r);
+
+       for (int i=0; i<floatimage.size(); ++i)
+               if (!floatimage.at(i)->isHidden())
+                       r=addBBox(floatimage.at(i)->getTotalBBox(),r);
+               
+       return r;
+}
+
+QRectF BranchObj::getBBoxSizeWithChilds()
+{
+       return bboxTotal;
+}
+
+void BranchObj::calcBBoxSizeWithChilds()
+{      
+       // This is initially called only from reposition and
+       // and only for mapcenter. So it won't be
+       // called more than once for a single user 
+       // action
+       
+
+       // Calculate size of LMO including all childs (to align them later)
+       bboxTotal.setX(bbox.x() );
+       bboxTotal.setY(bbox.y() );
+
+       // if branch is scrolled, ignore childs, but still consider floatimages
+       if (scrolled)
+       {
+               bboxTotal.setWidth (bbox.width());
+               bboxTotal.setHeight(bbox.height());
+               return;
+       }
+       
+       if (hidden)
+       {
+               bboxTotal.setWidth (0);
+               bboxTotal.setHeight(0);
+               if (parObj)
+               {
+                       bboxTotal.setX (parObj->x());
+                       bboxTotal.setY (parObj->y());
+               } else
+               {
+                       bboxTotal.setX (bbox.x());
+                       bboxTotal.setY (bbox.y());
+               }
+               return;
+       }
+       
+       QRectF r(0,0,0,0);
+       QRectF br;
+       // Now calculate recursivly
+       // sum of heights 
+       // maximum of widths 
+       // minimum of y
+       for (int i=0; i<branch.size(); ++i)
+       {
+               if (!branch.at(i)->isHidden())
+               {
+                       branch.at(i)->calcBBoxSizeWithChilds();
+                       br=branch.at(i)->getBBoxSizeWithChilds();
+                       r.setWidth( max (br.width(), r.width() ));
+                       r.setHeight(br.height() + r.height() );
+                       if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
+               }
+       }
+       // Add myself and also
+       // add width of link to sum if necessary
+       if (branch.isEmpty())
+               bboxTotal.setWidth (bbox.width() + r.width() );
+       else    
+               bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
+       
+       bboxTotal.setHeight(max (r.height(),  bbox.height()));
+}
+
+void BranchObj::select()
+{
+       // update NoteEditor
+       textEditor->setText(note.getNote() );
+       QString fnh=note.getFilenameHint();
+       if (fnh!="")
+               textEditor->setFilenameHint(note.getFilenameHint() );
+       else    
+               textEditor->setFilenameHint(getHeading() );
+       textEditor->setFontHint (note.getFontHint() );
+       isNoteInEditor=true;
+
+       // set selected and visible
+    LinkableMapObj::select();
+
+       // Tell parent that I am selected now:
+       BranchObj* po=(BranchObj*)(parObj);
+    if (po)    // TODO     Try to get rid of this cast...
+        po->setLastSelectedBranch(this);
+               
+       // temporary unscroll, if we have scrolled parents somewhere
+       if (parObj) ((BranchObj*)(parObj))->tmpUnscroll();
+
+       // Show URL and link in statusbar
+       QString status;
+       if (!url.isEmpty()) status+="URL: "+url+"  ";
+       if (!vymLink.isEmpty()) status+="Link: "+vymLink;
+       if (!status.isEmpty()) mainWindow->statusMessage (status);
+
+       // Update Toolbar
+       updateFlagsToolbar();
+
+       // Update actions
+       mapEditor->updateActions();
+}
+
+void BranchObj::unselect()
+{
+       LinkableMapObj::unselect();
+       // Delete any messages like vymLink in StatusBar
+       mainWindow->statusMessage ("");
+
+       // Save current note
+       if (isNoteInEditor) getNoteFromTextEditor();
+       isNoteInEditor=false;
+
+       // reset temporary unscroll, if we have scrolled parents somewhere
+       if (parObj) ((BranchObj*)(parObj))->resetTmpUnscroll();
+
+       // Erase content of editor 
+       textEditor->setInactive();
+
+       // unselect all buttons in toolbar
+       standardFlagsDefault->updateToolbar();
+}
+
+QString BranchObj::getSelectString()
+{
+       return mapEditor->getModel()->getSelectString (this);
+}
+
+void BranchObj::setAnimation(const AnimPoint &ap)
+{
+       anim=ap;
+}
+
+bool BranchObj::animate()
+{
+       anim.animate ();
+       if ( anim.isAnimated() )
+       {
+               setRelPos (anim);
+               return true;
+       }
+       parObj->reposition();   // object might have been relinked meanwhile
+       return false;
+}
+