3 #include "branchitem.h"
6 #include "mainwindow.h"
9 extern FlagRow *standardFlagsMaster;
10 extern FlagRow *systemFlagsMaster;
12 /////////////////////////////////////////////////////////////////
14 /////////////////////////////////////////////////////////////////
16 BranchObj::BranchObj () :OrnamentedObj() // FIXME-3 needed at all?
18 // cout << "Const BranchObj ()\n";
23 BranchObj::BranchObj (QGraphicsScene* s):OrnamentedObj (s)// FIXME-3 needed at all?
25 // cout << "Const BranchObj (s) \n";
31 BranchObj::BranchObj (QGraphicsScene* s, LinkableMapObj* p):OrnamentedObj (s)// FIXME-3 needed at all?
33 // cout << "Const BranchObj (s,p)\n";
36 if (treeItem->depth()==1)
37 // Calc angle to mapCenter if I am a mainbranch
38 // needed for reordering the mainbranches clockwise
40 angle=getAngle (QPointF (x() - parObj->getChildPos().x() ,
41 (y() - parObj->getChildPos().y() ) ) );
45 BranchObj::~BranchObj ()
47 // cout << "Destr BranchObj of "<<this<<" ("<<treeItem->getHeading().toStdString()<<")"<<endl;
49 // If I'm animated, I need to un-animate myself first
50 if (anim.isAnimated() )
52 anim.setAnimated (false);
53 model->stopAnimation (this);
56 // Check, if this branch was the last child to be deleted
57 // If so, unset the scrolled flags in parent // FIXME-2 better do this in model?
60 BranchObj *po=(BranchObj*)parObj;
64 bo=((BranchObj*)parObj)->getLastBranch();
65 if (bo) po->unScroll();
71 bool BranchObj::operator< ( const BranchObj & other )
73 return angle < other.angle;
76 bool BranchObj::operator== ( const BranchObj & other )
78 return angle == other.angle;
81 void BranchObj::init ()
86 absPos+=parObj->getChildPos();
91 includeImagesVer=false;
92 includeImagesHor=false;
95 void BranchObj::copy (BranchObj* other)
97 OrnamentedObj::copy(other);
99 for (int i=0; i<other->floatimage.size(); ++i)
100 addFloatImage (other->floatimage.at(i));
102 setVisibility (other->visible);
109 void BranchObj::clear()
111 //setVisibility (true); //FIXME-4 needed?
113 while (!floatimage.isEmpty())
114 delete floatimage.takeFirst();
116 while (!xlink.isEmpty())
117 delete xlink.takeFirst();
120 bool isAbove (BranchObj* a, BranchObj *b)
122 if (a->angle < b->angle)
128 void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPointF m, int off)
130 // Temporary link to lmo
131 // m is position of mouse pointer
132 // offset 0: default 1: below lmo -1 above lmo (if possible)
135 BranchObj* o=(BranchObj*)(lmo);
139 // ignore mapcenter and mainbranch
140 if (treeItem->depth()<2) off=0;
147 // FIXME-2 depth=parObj->getDepth()+1;
149 // setLinkStyle calls updateLink, only set it once
150 if (style!=getDefLinkStyle() ) setLinkStyle (getDefLinkStyle());
152 // Move temporary to new position at destination
153 // Usually the positioning would be done by reposition(),
154 // but then also the destination branch would "Jump" around...
155 // Better just do it approximately
156 if (treeItem->depth()==1)
157 { // new parent is the mapcenter itself
159 QPointF p= normalise ( QPointF (m.x() - o->getChildPos().x(),
160 m.y() - o->getChildPos().y() ));
161 if (p.x()<0) p.setX( p.x()-bbox.width() );
168 // new parent is just a branch, link to it
169 QRectF t=o->getBBoxSizeWithChildren();
170 if (o->getTreeItem()->getLastBranch())
171 y=t.y() + t.height() ;
178 // we want to link above lmo
179 y=o->y() - height() + 5;
181 // we want to link below lmo
182 // Bottom of sel should be 5 pixels above
183 // the bottom of the branch _below_ the target:
184 // Don't try to find that branch, guess 12 pixels
185 y=o->getChildPos().y() -height() + 12;
187 if (o->getOrientation()==LinkableMapObj::LeftOfCenter)
188 move ( o->getChildPos().x() - linkwidth, y );
190 move (o->getChildPos().x() + linkwidth, y );
193 // updateLink is called implicitly in move
197 void BranchObj::unsetParObjTmp()
204 //FIXME-2 depth=parObj->getDepth()+1;
205 setLinkStyle (getDefLinkStyle() );
210 void BranchObj::setVisibility(bool v, int toDepth)
212 BranchItem *bi=(BranchItem*)treeItem;
213 if (bi->depth() <= toDepth)
215 frame->setVisibility(v);
216 heading->setVisibility(v);
217 systemFlags->setVisibility(v);
218 standardFlags->setVisibility(v);
219 LinkableMapObj::setVisibility (v);
221 for (i=0; i<floatimage.size(); ++i)
222 floatimage.at(i)->setVisibility (v);
223 for (i=0; i<xlink.size(); ++i)
224 xlink.at(i)->setVisibility ();
226 // Only change children, if I am not scrolled
227 if (! bi->isScrolled() && (bi->depth() < toDepth))
229 // Now go recursivly through all children
230 for (i=0; i<treeItem->branchCount(); ++i)
231 treeItem->getBranchObjNum(i)->setVisibility (v,toDepth);
233 } // depth <= toDepth
237 void BranchObj::setVisibility(bool v)
239 setVisibility (v,MAX_DEPTH);
243 void BranchObj::setLinkColor ()
245 // Overloaded from LinkableMapObj
246 // BranchObj can use color of heading
250 if (model->getMapLinkColorHint()==HeadingColor)
251 LinkableMapObj::setLinkColor (heading->getColor() );
253 LinkableMapObj::setLinkColor ();
257 void BranchObj::setColorSubtree(QColor col)
260 for (int i=0; i<treeItem->branchCount(); ++i)
261 treeItem->getBranchObjNum(i)->setColorSubtree(col);
264 void BranchObj::updateContentSize()
271 void BranchObj::positionContents()
273 for (int i=0; i<floatimage.size(); ++i )
274 floatimage.at(i)->reposition();
275 OrnamentedObj::positionContents();
278 void BranchObj::move (double x, double y)
280 OrnamentedObj::move (x,y);
281 for (int i=0; i<floatimage.size(); ++i )
282 floatimage.at(i)->reposition();
286 void BranchObj::move (QPointF p)
291 void BranchObj::moveBy (double x, double y)
293 OrnamentedObj::moveBy (x,y);
294 for (int i=0; i<treeItem->branchCount(); ++i)
295 treeItem->getBranchObjNum(i)->moveBy (x,y);
299 void BranchObj::moveBy (QPointF p)
301 moveBy (p.x(), p.y());
305 void BranchObj::positionBBox()
307 QPointF ap=getAbsPos();
308 bbox.moveTopLeft (ap);
312 frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
314 // Update links to other branches
315 for (int i=0; i<xlink.size(); ++i)
316 xlink.at(i)->updateXLink();
319 void BranchObj::calcBBoxSize()
321 QSizeF heading_r=heading->getSize();
322 qreal heading_w=(qreal) heading_r.width() ;
323 qreal heading_h=(qreal) heading_r.height() ;
324 QSizeF sysflags_r=systemFlags->getSize();
325 qreal sysflags_h=sysflags_r.height();
326 qreal sysflags_w=sysflags_r.width();
327 QSizeF stanflags_r=standardFlags->getSize();
328 qreal stanflags_h=stanflags_r.height();
329 qreal stanflags_w=stanflags_r.width();
333 // set width to sum of all widths
334 w=heading_w + sysflags_w + stanflags_w;
335 // set height to maximum needed height
336 h=max (sysflags_h,stanflags_h);
339 // Save the dimension of flags and heading
340 ornamentsBBox.setSize ( QSizeF(w,h));
342 // clickBox includes Flags and Heading
343 clickBox.setSize (ornamentsBBox.size() );
348 topPad=botPad=leftPad=rightPad=0;
349 if (includeImagesVer || includeImagesHor)
351 if (treeItem->imageCount()>0)
353 for (int i=0; i<floatimage.size(); ++i )
355 rp=floatimage.at(i)->getRelPos();
356 if (includeImagesVer)
359 topPad=max (topPad,-rp.y()-h);
360 if (rp.y()+floatimage.at(i)->height() > 0)
361 botPad=max (botPad,rp.y()+floatimage.at(i)->height());
363 if (includeImagesHor)
365 if (orientation==LinkableMapObj::RightOfCenter)
368 leftPad=max (leftPad,-rp.x()-w);
369 if (rp.x()+floatimage.at(i)->width() > 0)
370 rightPad=max (rightPad,rp.x()+floatimage.at(i)->width());
374 leftPad=max (leftPad,-rp.x());
375 if (rp.x()+floatimage.at(i)->width() > w)
376 rightPad=max (rightPad,rp.x()+floatimage.at(i)->width()-w);
386 w+=frame->getPadding();
387 h+=frame->getPadding();
390 bbox.setSize (QSizeF (w,h));
393 void BranchObj::setDockPos()
395 // Sets childpos and parpos depending on orientation
396 if (getOrientation()==LinkableMapObj::LeftOfCenter )
399 ornamentsBBox.bottomLeft().x(),
402 ornamentsBBox.bottomRight().x(),
407 ornamentsBBox.bottomRight().x(),
410 ornamentsBBox.bottomLeft().x(),
415 void BranchObj::updateData()
420 qWarning ("BranchObj::udpateHeading treeItem==NULL");
423 QString s=treeItem->getHeading();
424 if (s!=heading->text())
426 heading->setText (s);
429 QStringList TIactiveFlags=treeItem->activeStandardFlagNames();
431 // Add missing standard flags active in TreeItem
432 for (int i=0;i<=TIactiveFlags.size()-1;i++)
434 if (!standardFlags->isActive (TIactiveFlags.at(i) ))
436 Flag *f=standardFlagsMaster->getFlag(TIactiveFlags.at(i));
437 if (f) standardFlags->activate (f);
441 // Remove standard flags no longer active in TreeItem
442 QStringList BOactiveFlags=standardFlags->activeFlagNames();
443 for (int i=0;i<BOactiveFlags.size();++i)
444 if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
446 standardFlags->deactivate (BOactiveFlags.at(i));
450 // Add missing system flags active in TreeItem
451 TIactiveFlags=treeItem->activeSystemFlagNames();
452 for (int i=0;i<TIactiveFlags.size();++i)
454 if (!systemFlags->isActive (TIactiveFlags.at(i) ))
456 Flag *f=systemFlagsMaster->getFlag(TIactiveFlags.at(i));
457 if (f) systemFlags->activate (f);
461 // Remove system flags no longer active in TreeItem
462 BOactiveFlags=systemFlags->activeFlagNames();
463 for (int i=0;i<BOactiveFlags.size();++i)
465 if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
467 systemFlags->deactivate (BOactiveFlags.at(i));
477 void BranchObj::addXLink (XLinkObj *xlo)
483 void BranchObj::removeXLinkRef (XLinkObj *xlo)
485 xlink.removeAt (xlink.indexOf(xlo));
488 void BranchObj::deleteXLink(XLinkObj *xlo)
491 if (!xlo->isUsed()) delete (xlo);
494 void BranchObj::deleteXLinkAt (int i)
496 XLinkObj *xlo=xlink.at(i);
498 if (!xlo->isUsed()) delete(xlo);
501 XLinkObj* BranchObj::XLinkAt (int i)
506 BranchObj* BranchObj::XLinkTargetAt (int i)
508 if (i>=0 && i<xlink.size())
511 return xlink.at(i)->otherBranch (this);
516 void BranchObj::setIncludeImagesVer(bool b)
524 bool BranchObj::getIncludeImagesVer()
526 return includeImagesVer;
529 void BranchObj::setIncludeImagesHor(bool b)
537 bool BranchObj::getIncludeImagesHor()
539 return includeImagesHor;
542 QString BranchObj::getIncludeImageAttr()
545 if (includeImagesVer)
546 a=attribut ("incImgV","true");
548 a=attribut ("incImgV","false");
549 if (includeImagesHor)
550 a+=attribut ("incImgH","true");
552 a+=attribut ("incImgH","false");
556 FloatImageObj* BranchObj::addFloatImage ()
558 FloatImageObj *newfi=new FloatImageObj (scene,this);
559 floatimage.append (newfi);
560 if ( ((BranchItem*)treeItem)->hasScrolledParent((BranchItem*)treeItem) )
561 newfi->setVisibility (false);
563 newfi->setVisibility(visible);
572 FloatImageObj* BranchObj::addFloatImage (FloatImageObj *fio)
574 FloatImageObj *newfi=new FloatImageObj (scene,this);
575 floatimage.append (newfi);
577 if (((BranchItem*)treeItem)->hasScrolledParent((BranchItem*)treeItem) )
578 newfi->setVisibility (false);
580 newfi->setVisibility(visible);
589 FloatImageObj* BranchObj::getFirstFloatImage ()
591 return floatimage.first();
594 FloatImageObj* BranchObj::getLastFloatImage ()
596 return floatimage.last();
599 FloatImageObj* BranchObj::getFloatImageNum (const uint &i)
601 return floatimage.at(i);
604 void BranchObj::removeFloatImage (FloatImageObj *fio)
606 int i=floatimage.indexOf (fio);
607 if (i>-1) delete (floatimage.takeAt (i));
613 void BranchObj::savePosInAngle ()
615 // Save position in angle
616 for (int i=0; i<treeItem->branchCount(); ++i)
617 treeItem->getBranchObjNum(i)->angle=i;
620 void BranchObj::setDefAttr (BranchModification mod)
623 switch (treeItem->depth())
625 case 0: fontsize=16; break;
626 case 1: fontsize=12; break;
627 default: fontsize=10; break;
631 setLinkStyle(getDefLinkStyle());
632 QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
633 font.setPointSize(fontsize);
634 heading->setFont(font );
637 setColor (treeItem->getHeadingColor() );
641 void BranchObj::removeBranchHere(BranchObj* borem) // FIXME-2 getNum no longer available
644 // This removes the branch bo from list, but
645 // inserts its children at the place of bo
647 bo=borem->getLastBranch();
648 int pos=borem->getNum();
651 bo->linkTo (this,pos+1);
652 bo=borem->getLastBranch();
654 removeBranch (borem);
658 void BranchObj::removeChildren() // FIXME-3 not needed here
663 void BranchObj::removeBranch(BranchObj* bo) // FIXME-2 not needed here
666 // if bo is not in branch remove returns false, we
669 int i=branch.indexOf(bo);
675 qWarning ("BranchObj::removeBranch tried to remove non existing branch?!\n");
680 void BranchObj::removeBranchPtr(BranchObj* bo) // FIXME-3 not needed here
683 int i=branch.indexOf(bo);
688 qWarning ("BranchObj::removeBranchPtr tried to remove non existing branch?!\n");
693 void BranchObj::sortChildren() //FIXME-2
696 int childCount=branch.count();
698 bool madeChanges=false;
702 for(curChildIndex=1;curChildIndex<childCount;curChildIndex++){
703 BranchObj* curChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex);
704 BranchObj* prevChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex-1);
705 if(prevChild->heading->text().compare(curChild->heading->text())>0)
707 this->moveBranchUp(curChild);
715 void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
717 qreal th = bboxTotal.height();
718 int depth=treeItem->depth();
722 QString h=QString (depth,' ');
723 h+=treeItem->getHeading();
726 QPointF pp; if (parObj) pp=parObj->getChildPos();
727 cout << "BO::alignRelTo ";
728 cout<<h.toStdString();
729 cout << " d="<<depth<<
730 //cout<< " ref="<<ref<<
731 " bbox.tL="<<bboxTotal.topLeft()<<
733 // " relPos="<<relPos<<
735 " w="<<bbox.width()<<
736 " h="<<bbox.height()<<
737 // " orient="<<orientation<<
738 // " alignSelf="<<alignSelf<<
739 // " scrolled="<<((BranchItem*)treeItem)->isScrolled()<<
740 // " pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
741 // " hidden="<<hidden<<
749 if (depth==1 && parObj)
751 // Position relatively, if needed
752 //if (useRelPos) move2RelPos (relPos.x(), relPos.y());
754 // Calc angle to mapCenter if I am a mainbranch
755 // needed for reordering the mainbranches clockwise
757 angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ),
758 (int)(y() - parObj->getChildPos().y() ) ) );
762 // Align myself depending on orientation and parent, but
763 // only if I am not a mainbranch or mapcenter itself
765 if (anim.isAnimated())
770 LinkableMapObj::Orientation o;
771 o=parObj->getOrientation();
775 case LinkableMapObj::LeftOfCenter:
776 move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
777 //move (ref.x() , ref.y() + (th-bbox.height())/2 );
779 case LinkableMapObj::RightOfCenter:
780 move (ref.x() , ref.y() + (th-bbox.height())/2 );
783 qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
789 if ( ((BranchItem*)treeItem)->isScrolled() ) return;
791 // Set reference point for alignment of children
793 if (orientation==LinkableMapObj::LeftOfCenter)
794 ref2.setX(bbox.topLeft().x() - linkwidth);
796 ref2.setX(bbox.topRight().x() + linkwidth);
799 ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
803 // Align the children depending on reference point
804 for (int i=0; i<treeItem->branchCount(); ++i)
806 if (!treeItem->getBranchNum(i)->isHidden())
808 treeItem->getBranchObjNum(i)->alignRelativeTo (ref2,true);
810 // append next branch below current one
811 ref2.setY(ref2.y() + treeItem->getBranchObjNum(i)->getBBoxSizeWithChildren().height() );
817 void BranchObj::reposition()
820 if (!treeItem->getHeading().isEmpty())
821 cout << "BO::reposition "<<qPrintable(treeItem->getHeading())<<endl;
823 cout << "BO::reposition ???"<<endl;
824 // cout << " orient="<<orientation<<endl;
827 if (treeItem->depth()==0)
829 // only calculate the sizes once. If the deepest LMO
830 // changes its height,
831 // all upper LMOs have to change, too.
832 calcBBoxSizeWithChildren();
833 updateLink(); // This update is needed if the scene is resized
834 // due to excessive moving of a FIO
836 alignRelativeTo ( QPointF (absPos.x(),
837 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
838 //FIXME-2 qSort (branch.begin(),branch.end(), isAbove);
839 positionBBox(); // Reposition bbox and contents
842 // This is only important for moving branches:
843 // For editing a branch it isn't called...
844 alignRelativeTo ( QPointF (absPos.x(),
845 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
849 void BranchObj::unsetAllRepositionRequests()
851 repositionRequest=false;
852 for (int i=0; i<treeItem->branchCount(); ++i)
853 treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
857 QPolygonF BranchObj::shape()
861 QRectF r=getTotalBBox();
862 if (orientation==LinkableMapObj::LeftOfCenter)
865 <<QPointF (bbox.topLeft().x(), r.topLeft().y() )
868 <<QPointF (bbox.bottomLeft().x(), r.bottomLeft().y() ) ;
872 <<QPointF (bbox.topRight().x(), r.topRight().y() )
875 <<QPointF (bbox.bottomRight().x(), r.bottomRight().y() ) ;
879 QRectF BranchObj::getTotalBBox()
883 if ( ((BranchItem*)treeItem)->isScrolled() ) return r;
885 for (int i=0; i<treeItem->branchCount(); ++i)
886 if (!treeItem->getBranchNum(i)->isHidden())
887 r=addBBox(treeItem->getBranchObjNum(i)->getTotalBBox(),r);
889 /* FIXME-3 lots of occurences of treeItem->getBranchObjNum(i) in branchobj.cpp
890 better check if they are not NULL and maybe simplify...
891 (have been NULL at least in calcBBoxSizeWithChilds...)
895 FIXME-1 for (int i=0; i<floatimage.size(); ++i)
896 if (!floatimage.at(i)->isHidden())
897 r=addBBox(floatimage.at(i)->getTotalBBox(),r);
902 QRectF BranchObj::getBBoxSizeWithChildren()
907 void BranchObj::calcBBoxSizeWithChildren()
909 // This is initially called only from reposition and
910 // and only for mapcenter. So it won't be
911 // called more than once for a single user
915 // Calculate size of LMO including all children (to align them later)
916 bboxTotal.setX(bbox.x() );
917 bboxTotal.setY(bbox.y() );
919 // if branch is scrolled, ignore children, but still consider floatimages
920 BranchItem *bi=(BranchItem*)treeItem;
921 if ( bi->isScrolled() )
923 bboxTotal.setWidth (bbox.width());
924 bboxTotal.setHeight(bbox.height());
930 bboxTotal.setWidth (0);
931 bboxTotal.setHeight(0);
934 bboxTotal.setX (parObj->x());
935 bboxTotal.setY (parObj->y());
938 bboxTotal.setX (bbox.x());
939 bboxTotal.setY (bbox.y());
946 // Now calculate recursivly
950 for (int i=0; i<treeItem->branchCount(); i++)
952 if (!bi->getBranchNum(i)->isHidden())
954 bi->getBranchObjNum(i)->calcBBoxSizeWithChildren();
955 br=bi->getBranchObjNum(i)->getBBoxSizeWithChildren();
956 r.setWidth( max (br.width(), r.width() ));
957 r.setHeight(br.height() + r.height() );
958 if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
961 // Add myself and also
962 // add width of link to sum if necessary
963 if (bi->branchCount()<1)
964 bboxTotal.setWidth (bbox.width() + r.width() );
966 bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
968 bboxTotal.setHeight(max (r.height(), bbox.height()));
971 QString BranchObj::getSelectString()
973 return model->getSelectString (this);
976 void BranchObj::setAnimation(const AnimPoint &ap)
981 bool BranchObj::animate()
984 if ( anim.isAnimated() )
989 parObj->reposition(); // we might have been relinked meanwhile