#include "branchobj.h" #include "texteditor.h" #include "mapeditor.h" #include "mainwindow.h" extern TextEditor *textEditor; extern Main *mainWindow; extern FlagRowObj *standardFlagsDefault; extern QAction *actionEditOpenURL; ///////////////////////////////////////////////////////////////// // BranchObj ///////////////////////////////////////////////////////////////// BranchObj* BranchObj::itLast=NULL; BranchObj::BranchObj () :OrnamentedObj() { // cout << "Const BranchObj ()\n"; setParObj (this); init(); depth=-1; } BranchObj::BranchObj (QCanvas* c):OrnamentedObj (c) { // cout << "Const BranchObj (c) called from MapCenterObj (c)\n"; parObj=NULL; canvas=c; } BranchObj::BranchObj (QCanvas* c, LinkableMapObj* p):OrnamentedObj (c) { // cout << "Const BranchObj (c,p)\n"; canvas=c; 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 (QPoint ((int)(x() - parObj->getChildPos().x() ), (int)(y() - parObj->getChildPos().y() ) ) ); init(); } BranchObj::~BranchObj () { // cout << "Destr BranchObj of "<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; } int BranchObjPtrList::compareItems ( QPtrCollection::Item i, QPtrCollection::Item j) { // Make sure PtrList::find works if (i==j) return 0; if ( ((BranchObj*)(i))->angle > ((BranchObj*)(j))->angle ) return 1; else return -1; } void BranchObj::init () { branch.setAutoDelete (false); floatimage.setAutoDelete (true); xlink.setAutoDelete (false); if (parObj) { absPos=getRandPos(); absPos+=parObj->getChildPos(); } lastSelectedBranch=-1; setChildObj(this); scrolled=false; tmpUnscrolled=false; includeImagesVer=false; includeImagesHor=false; } void BranchObj::copy (BranchObj* other) { OrnamentedObj::copy(other); branch.clear(); BranchObj* b; for (b=other->branch.first(); b;b=other->branch.next() ) // Make deep copy of b // Because addBranch again calls copy for the childs, // Those will get a deep copy, too addBranch(b); FloatImageObj *fi; for (fi=other->floatimage.first(); fi;fi=other->floatimage.next() ) addFloatImage (fi); scrolled=other->scrolled; tmpUnscrolled=other->tmpUnscrolled; setVisibility (other->visible); angle=other->angle; positionBBox(); } void BranchObj::clear() { floatimage.clear(); while (!xlink.isEmpty()) deleteXLink (xlink.first() ); BranchObj *bo; while (!branch.isEmpty()) { bo=branch.first(); branch.removeFirst(); delete (bo); } } int BranchObj::getNum() { if (parObj) return ((BranchObj*)(parObj))->getNum ((BranchObj*)(this)); else return 0; } int BranchObj::getNum(BranchObj *bo) { // keep current pointer in branch, // otherwise save might fail int cur=branch.at(); int ind=branch.findRef (bo); branch.at(cur); return ind; } int BranchObj::getFloatImageNum(FloatImageObj *fio) { return floatimage.findRef (fio); } int BranchObj::countBranches() { return branch.count(); } int BranchObj::countFloatImages() { return floatimage.count(); } int BranchObj::countXLinks() { return xlink.count(); } void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPoint 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 QPoint p= normalise ( QPoint (m.x() - o->getChildPos().x(), m.y() - o->getChildPos().y() )); if (p.x()<0) p.setX( p.x()-bbox.width() ); move2RelPos (p); } else { int y; if (off==0) { // new parent is just a branch, link to it QRect 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()==OrientLeftOfCenter) move ( o->getChildPos().x() - linkwidth, y ); else move (o->getChildPos().x() + linkwidth, y ); } // updateLink is called implicitly in move reposition(); // FIXME shouldn't be this a request? } 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() { BranchObj *bo; if (scrolled) { scrolled=false; systemFlags->deactivate("scrolledright"); for (bo=branch.first(); bo; bo=branch.next() ) { bo->setVisibility(true); } } else { scrolled=true; systemFlags->activate("scrolledright"); for (bo=branch.first(); bo; bo=branch.next() ) { bo->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 BranchObj* b; for (b=branch.first(); b;b=branch.next() ) b->setVisibility (v,toDepth); FloatImageObj *fio; for (fio=floatimage.first(); fio; fio=floatimage.next()) fio->setVisibility (v); XLinkObj* xlo; for (xlo=xlink.first(); xlo;xlo=xlink.next() ) xlo->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->getLinkColorHint()==HeadingColor) LinkableMapObj::setLinkColor (heading->getColor() ); else LinkableMapObj::setLinkColor (); } void BranchObj::setColorChilds (QColor col) { OrnamentedObj::setColor (col); BranchObj *bo; for (bo=branch.first(); bo; bo=branch.next() ) bo->setColorChilds(col); } BranchObj* BranchObj::first() { itLast=NULL; return this; } BranchObj* BranchObj::next() { BranchObj *lmo; BranchObj *bo=branch.first(); BranchObj *po=(BranchObj*)(parObj); if (!itLast) { // We are just beginning at the mapCenter if (bo) { itLast=this; return bo; } else { itLast=NULL; return NULL; } } if (itLast==parObj) { // We come from above if (bo) { // there are childs, go there itLast=this; return bo; } else { // no childs, try to go up again 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; } } } // Try to find last child, we came from, in my own childs bool searching=true; while (bo && searching) { if (itLast==bo) searching=false; bo=branch.next(); } if (!searching) { // found lastLMO in my childs if (bo) { // found a brother of lastLMO itLast=this; return bo; } else { 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; } } } // couldn't find last child, it must be a nephew of mine bo=branch.first(); if (bo) { // proceed with my first child itLast=this; return bo; } 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() { FloatImageObj *fio; for (fio=floatimage.first(); fio; fio=floatimage.next() ) fio->reposition(); OrnamentedObj::positionContents(); } void BranchObj::move (double x, double y) { OrnamentedObj::move (x,y); FloatImageObj *fio; for (fio=floatimage.first(); fio; fio=floatimage.next() ) fio->reposition(); positionBBox(); } void BranchObj::move (QPoint p) { move (p.x(), p.y()); } void BranchObj::moveBy (double x, double y) { OrnamentedObj::moveBy (x,y); BranchObj* b; for (b=branch.first(); b;b=branch.next() ) b->moveBy (x,y); positionBBox(); } void BranchObj::moveBy (QPoint p) { moveBy (p.x(), p.y()); } void BranchObj::positionBBox() { QPoint ap=getAbsPos(); bbox.moveTopLeft (ap); positionContents(); setSelBox(); // set the frame frame->setRect(QRect(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) ); // Update links to other branches XLinkObj *xlo; for (xlo=xlink.first(); xlo; xlo=xlink.next() ) xlo->updateXLink(); } void BranchObj::calcBBoxSize() { QSize heading_r=heading->getSize(); int heading_w=(int) heading_r.width() ; int heading_h=(int) heading_r.height() ; QSize sysflags_r=systemFlags->getSize(); int sysflags_h=sysflags_r.height(); int sysflags_w=sysflags_r.width(); QSize stanflags_r=standardFlags->getSize(); int stanflags_h=stanflags_r.height(); int stanflags_w=stanflags_r.width(); int w; int 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 ( QSize(w,h)); // clickBox includes Flags and Heading clickBox.setSize (ornamentsBBox.size() ); // Floatimages QPoint rp; FloatImageObj *foi; topPad=botPad=leftPad=rightPad=0; if (includeImagesVer || includeImagesHor) { if (countFloatImages()>0) { for (foi=floatimage.first(); foi; foi=floatimage.next() ) { rp=foi->getRelPos(); if (includeImagesVer) { if (rp.y() < 0) topPad=max (topPad,-rp.y()-h); if (rp.y()+foi->height() > 0) botPad=max (botPad,rp.y()+foi->height()); } if (includeImagesHor) { if (orientation==OrientRightOfCenter) { if (-rp.x()-w > 0) leftPad=max (leftPad,-rp.x()-w); if (rp.x()+foi->width() > 0) rightPad=max (rightPad,rp.x()+foi->width()); } else { if (rp.x()< 0) leftPad=max (leftPad,-rp.x()); if (rp.x()+foi->width() > w) rightPad=max (rightPad,rp.x()+foi->width()-w); } } } } h+=topPad+botPad; w+=leftPad+rightPad; } // Frame thickness w+=frame->getBorder(); h+=frame->getBorder(); // Finally set size bbox.setSize (QSize (w,h)); } void BranchObj::setDockPos() { if (getOrientation()==OrientLeftOfCenter ) { childPos=QPoint (ornamentsBBox.bottomLeft().x(), ornamentsBBox.bottomLeft().y() ); parPos=QPoint (ornamentsBBox.bottomRight().x(),ornamentsBBox.bottomRight().y() ); } else { childPos=QPoint (ornamentsBBox.bottomRight().x(), ornamentsBBox.bottomRight().y() ); parPos=QPoint (ornamentsBBox.bottomLeft().x(),ornamentsBBox.bottomLeft().y() ); } } LinkableMapObj* BranchObj::findMapObj(QPoint p, LinkableMapObj* excludeLMO) { // Search branches BranchObj *b; LinkableMapObj *lmo; for (b=branch.first(); b; b=branch.next() ) { lmo=b->findMapObj(p, excludeLMO); if (lmo != NULL) return lmo; } // Search myself if (inBox (p) && (this != excludeLMO) && isVisibleObj() ) return this; // Search float images FloatImageObj *foi; for (foi=floatimage.first(); foi; foi=floatimage.next() ) if (foi->inBox(p) && (foi != excludeLMO) && foi->getParObj()!= excludeLMO && foi->isVisibleObj() ) return foi; 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 && hasHiddenExportParent(this)) { setVisibility (false); hidden=true; }else { if (hasScrolledParent(this)) setVisibility (false); else setVisibility (true); hidden=false; } BranchObj *bo; for (bo=branch.first(); bo; bo=branch.next() ) bo->setHideTmp (mode); } bool BranchObj::hasHiddenExportParent(BranchObj *start) { // Calls parents recursivly to // find out, if we are temp. hidden if (hideExport) return true; BranchObj* bo=(BranchObj*)(parObj); if (bo) return bo->hasHiddenExportParent(start); else return false; } QString BranchObj::saveToDir (const QString &tmpdir,const QString &prefix, const QPoint& offset) { if (hidden) return ""; QString s,a; QString scrolledAttr; if (scrolled) scrolledAttr=attribut ("scrolled","yes"); else scrolledAttr=""; QString frameAttr; if (frame->getFrameType()!=NoFrame) frameAttr=attribut ("frameType",frame->getFrameTypeName()); else frameAttr=""; // save area, if not scrolled QString areaAttr; if (!((BranchObj*)(parObj))->isScrolled() ) { areaAttr= attribut("x1",QString().setNum(absPos.x()-offset.x(),10)) + attribut("y1",QString().setNum(absPos.y()-offset.y(),10)) + attribut("x2",QString().setNum(absPos.x()+width()-offset.x(),10)) + attribut("y2",QString().setNum(absPos.y()+height()-offset.y(),10)); } else areaAttr=""; // Providing an ID for a branch makes export to XHTML easier QString idAttr; if (countXLinks()>0) idAttr=attribut ("id",getSelectString()); else idAttr=""; s=beginElement ("branch" +getOrnAttr() +scrolledAttr +frameAttr +areaAttr +idAttr +getIncludeImageAttr() ); incIndent(); // save heading s+=valueElement("heading", getHeading(), attribut ("textColor",QColor(heading->getColor()).name())); // save names of flags set s+=standardFlags->saveToDir(tmpdir,prefix,0); // save note if (!note.isEmpty() ) s+=note.saveToDir(); // Save branches BranchObj *bo; for (bo=branch.first(); bo; bo=branch.next() ) s+=bo->saveToDir(tmpdir,prefix,offset); // Save FloatImages FloatImageObj *fio; for (fio=floatimage.first(); fio; fio=floatimage.next() ) s+=fio->saveToDir (tmpdir,prefix,offset); // Save XLinks XLinkObj *xlo; //FIXME exponential increase in xlinks... QString ol; // old link QString cl; // current link for (xlo=xlink.first(); xlo; xlo=xlink.next() ) { cl=xlo->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.remove (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 (xlink.at(i)) return xlink.at(i)->otherBranch (this); else return NULL; } void BranchObj::setIncludeImagesVer(bool b) { includeImagesVer=b; calcBBoxSize(); positionBBox(); requestReposition(); //FIXME undo needed } bool BranchObj::getIncludeImagesVer() { return includeImagesVer; } void BranchObj::setIncludeImagesHor(bool b) { includeImagesHor=b; calcBBoxSize(); positionBBox(); requestReposition(); //FIXME undo needed } 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; } LinkableMapObj* BranchObj::addFloatImage () { FloatImageObj *newfi=new FloatImageObj (canvas,this); floatimage.append (newfi); if (hasScrolledParent(this) ) newfi->setVisibility (false); else newfi->setVisibility(visible); calcBBoxSize(); positionBBox(); requestReposition(); return newfi; //FIXME undo needed } LinkableMapObj* BranchObj::addFloatImage (FloatImageObj *fio) { FloatImageObj *newfi=new FloatImageObj (canvas,this); floatimage.append (newfi); newfi->copy (fio); if (hasScrolledParent(this) ) newfi->setVisibility (false); else newfi->setVisibility(visible); calcBBoxSize(); positionBBox(); requestReposition(); return newfi; // FIMXE undo needed } 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) { floatimage.remove (fio); calcBBoxSize(); positionBBox(); requestReposition(); // FIMXE undo needed } void BranchObj::savePosInAngle () { // Save position in angle BranchObj *b; int i=0; for (b=branch.first(); b; b=branch.next() ) { b->angle=i; 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(canvas,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(canvas,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; branch.sort(); 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); branch.sort(); 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); branch.sort(); 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->moveBranchTo (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... if (branch.remove (bo)) delete (bo); else qWarning ("BranchObj::removeBranch tried to remove non existing branch?!\n"); requestReposition(); } void BranchObj::removeBranchPtr(BranchObj* bo) { branch.remove (bo); requestReposition(); } void BranchObj::setLastSelectedBranch (BranchObj* bo) { lastSelectedBranch=branch.find(bo); } BranchObj* BranchObj::getLastSelectedBranch () { if (lastSelectedBranch>=0) { BranchObj* bo=branch.at(lastSelectedBranch); if (bo) return bo; } return branch.first(); } BranchObj* BranchObj::getFirstBranch () { return branch.first(); } BranchObj* BranchObj::getLastBranch () { return branch.last(); } BranchObj* BranchObj::getBranchNum (const uint &i) { return branch.at(i); } bool BranchObj::canMoveBranchUp() { if (!parObj) return false; BranchObj* par=(BranchObj*)parObj; if (this==par->getFirstBranch()) return false; else return true; } BranchObj* BranchObj::moveBranchUp(BranchObj* bo1) // move a branch up (modify myself) { savePosInAngle(); int i=branch.find(bo1); if (i>0) { // -1 if bo1 not found branch.at(i)->angle--; branch.at(i-1)->angle++; branch.sort(); return branch.at(i-1); } else return branch.at(i); } bool BranchObj::canMoveBranchDown() { if (!parObj) return false; BranchObj* par=(BranchObj*)parObj; if (this==par->getLastBranch()) return false; else return true; } BranchObj* BranchObj::moveBranchDown(BranchObj* bo1) { savePosInAngle(); int i=branch.find(bo1); int j; if (branch.next()) { j = branch.at(); branch.at(i)->angle++; branch.at(j)->angle--; branch.sort(); return branch.at(j); } else return branch.at(i); } BranchObj* BranchObj::moveBranchTo (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 (QPoint ref) { int th = bboxTotal.height(); // TODO testing /* cout << "BO::alignRelTo "<