3 #include "branchitem.h"
6 #include "mainwindow.h"
9 extern FlagRow *standardFlagsMaster;
10 extern FlagRow *systemFlagsMaster;
12 /////////////////////////////////////////////////////////////////
14 /////////////////////////////////////////////////////////////////
16 BranchObj::BranchObj (QGraphicsScene* s,TreeItem *ti):OrnamentedObj (s)
18 // cout << "Const BranchObj (s) \n";
21 BranchItem *pi=(BranchItem*)(ti->parent());
22 if (pi && pi!=ti->getModel()->getRootItem() )
30 BranchObj::BranchObj (QGraphicsScene* s, LinkableMapObj* p):OrnamentedObj (s)// FIXME-3 needed at all?
32 // cout << "Const BranchObj (s,p)\n";
35 if (treeItem->depth()==1) // FIXME-3 needed to recursively calc depth?
36 // Calc angle to mapCenter if I am a mainbranch
37 // needed for reordering the mainbranches clockwise
39 angle=getAngle (QPointF (x() - parObj->getChildPos().x() ,
40 (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 VymModel *model=treeItem->getModel();
54 model->stopAnimation (this);
57 // Check, if this branch was the last child to be deleted
58 // If so, unset the scrolled flags in parent // FIXME-2 better do this in model?
61 BranchObj *po=(BranchObj*)parObj;
65 bo=((BranchObj*)parObj)->getLastBranch();
66 if (bo) po->unScroll();
72 bool BranchObj::operator< ( const BranchObj & other )
74 return angle < other.angle;
77 bool BranchObj::operator== ( const BranchObj & other )
79 return angle == other.angle;
82 void BranchObj::init ()
87 absPos+=parObj->getChildPos();
91 void BranchObj::copy (BranchObj* other)
93 OrnamentedObj::copy(other);
95 setVisibility (other->visible);
102 void BranchObj::clear()
104 //setVisibility (true); //FIXME-4 needed?
106 while (!xlink.isEmpty())
107 delete xlink.takeFirst();
110 bool isAbove (BranchObj* a, BranchObj *b)
112 if (a->angle < b->angle)
118 void BranchObj::setParObjTmp(LinkableMapObj* dst, QPointF m, int off) //FIXME-1 when moving a mainbranch to a branch it still has relPos, not moved as child
120 // Temporary link to dst
121 // m is position of mouse pointer
122 // offset 0: default 1: below dst -1 above dst (if possible)
124 BranchItem *dsti=(BranchItem*)(dst->getTreeItem());
126 BranchItem *pi=(BranchItem*)(dsti->parent());
127 int pi_depth=pi->depth();
128 BranchObj* bodst=(BranchObj*)dst;
136 if (pi_depth<2) off=0;
143 setLinkStyle (dst->getDefLinkStyle (dsti));
145 // Move temporary to new position at destination
146 // Usually the positioning would be done by reposition(),
147 // but then also the destination branch would "Jump" around...
148 // Better just do it approximately
149 cout << "BO::setTmp ";
150 if (dsti->depth()==0)
151 { // new parent is a mapcenter
152 Vector v= ( m - bodst->getChildPos());
153 if (v.x()<0) v.setX( v.x()-bbox.width() );
156 move2RelPos (v.toQPointF());
157 cout << " v="<<v<<endl;
163 // new parent is just a branch, link to it
164 QRectF t=bodst->getBBoxSizeWithChildren();
165 if (dsti->getLastBranch())
166 y=t.y() + t.height() ;
172 cout << " t.h="<<t.height();
177 // we want to link above dst
178 y=bodst->y() - height() + 5;
180 // we want to link below dst
181 // Bottom of sel should be 5 pixels above
182 // the bottom of the branch _below_ the target:
183 // Don't try to find that branch, guess 12 pixels
184 y=bodst->getChildPos().y() -height() + 12;
186 cout << " pos="<<getAbsPos()<<" cPos="<<bodst->getChildPos()<<endl;
187 if (bodst->getOrientation()==LinkableMapObj::LeftOfCenter)
188 move ( bodst->getChildPos().x() - linkwidth, y );
190 move (bodst->getChildPos().x() + linkwidth, y );
193 // updateLinkGeometry is called implicitly in move
197 void BranchObj::unsetParObjTmp()
205 setLinkStyle (getDefLinkStyle(treeItem->parent() ) );
206 updateLinkGeometry();
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<treeItem->imageCount(); ++i)
222 treeItem->getImageObjNum(i)->setVisibility (v);
223 for (i=0; i<treeItem->xlinkCount(); ++i)
224 treeItem->getXLinkObjNum(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 //FIXME-3 are there multiple calls for lower level items???
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
248 VymModel *model=treeItem->getModel();
251 if (model->getMapLinkColorHint()==HeadingColor)
252 LinkableMapObj::setLinkColor (heading->getColor() );
254 LinkableMapObj::setLinkColor ();
258 void BranchObj::updateContentSize()
265 void BranchObj::positionContents()
267 for (int i=0; i<treeItem->imageCount(); ++i)
268 treeItem->getImageObjNum(i)->reposition();
269 OrnamentedObj::positionContents();
272 void BranchObj::move (double x, double y)
274 OrnamentedObj::move (x,y);
278 void BranchObj::move (QPointF p)
283 void BranchObj::moveBy (double x, double y)
285 OrnamentedObj::moveBy (x,y);
286 for (int i=0; i<treeItem->branchCount(); ++i)
287 treeItem->getBranchObjNum(i)->moveBy (x,y);
291 void BranchObj::moveBy (QPointF p)
293 moveBy (p.x(), p.y());
297 void BranchObj::positionBBox()
299 QPointF ap=getAbsPos();
300 bbox.moveTopLeft (ap);
304 frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
306 //Update links to other branches
308 for (int i=0; i<treeItem->xlinkCount(); ++i)
310 xlo=treeItem->getXLinkObjNum(i);
311 if (xlo) xlo->updateXLink();
315 void BranchObj::calcBBoxSize()
317 QSizeF heading_r=heading->getSize();
318 qreal heading_w=(qreal) heading_r.width() ;
319 qreal heading_h=(qreal) heading_r.height() ;
320 QSizeF sysflags_r=systemFlags->getSize();
321 qreal sysflags_h=sysflags_r.height();
322 qreal sysflags_w=sysflags_r.width();
323 QSizeF stanflags_r=standardFlags->getSize();
324 qreal stanflags_h=stanflags_r.height();
325 qreal stanflags_w=stanflags_r.width();
329 // set width to sum of all widths
330 w=heading_w + sysflags_w + stanflags_w;
331 // set height to maximum needed height
332 h=max (sysflags_h,stanflags_h);
335 // Save the dimension of flags and heading
336 ornamentsBBox.setSize ( QSizeF(w,h));
338 // clickBox includes Flags and Heading
339 clickBox.setSize (ornamentsBBox.size() );
344 topPad=botPad=leftPad=rightPad=0;
345 bool incV=((BranchItem*)treeItem)->getIncludeImagesVer();
346 bool incH=((BranchItem*)treeItem)->getIncludeImagesHor();
350 for (int i=0; i<treeItem->imageCount(); ++i )
352 fio=treeItem->getImageObjNum(i);
357 topPad=max (topPad,-rp.y()-h);
358 if (rp.y()+fio->height() > 0)
359 botPad=max (botPad,rp.y()+fio->height());
363 if (orientation==LinkableMapObj::RightOfCenter)
366 leftPad=max (leftPad,-rp.x()-w);
367 if (rp.x()+fio->width() > 0)
368 rightPad=max (rightPad,rp.x()+fio->width());
372 leftPad=max (leftPad,-rp.x());
373 if (rp.x()+fio->width() > w)
374 rightPad=max (rightPad,rp.x()+fio->width()-w);
383 w+=frame->getPadding();
384 h+=frame->getPadding();
387 bbox.setSize (QSizeF (w,h));
390 void BranchObj::setDockPos()
392 if (treeItem->getType()==TreeItem::MapCenter)
394 // set childPos to middle of MapCenterObj
395 childPos.setX( clickBox.topLeft().x() + clickBox.width()/2 );
396 childPos.setY( clickBox.topLeft().y() + clickBox.height()/2 );
398 for (int i=0; i<treeItem->branchCount(); ++i)
399 treeItem->getBranchObjNum(i)->updateLinkGeometry();
403 // Sets childpos and parpos depending on orientation
404 if (getOrientation()==LinkableMapObj::LeftOfCenter )
407 ornamentsBBox.bottomLeft().x(),
410 ornamentsBBox.bottomRight().x(),
415 ornamentsBBox.bottomRight().x(),
418 ornamentsBBox.bottomLeft().x(),
424 void BranchObj::updateData()
429 qWarning ("BranchObj::udpateHeading treeItem==NULL");
432 QString s=treeItem->getHeading();
433 if (s!=heading->text())
435 heading->setText (s);
438 QStringList TIactiveFlags=treeItem->activeStandardFlagNames();
440 // Add missing standard flags active in TreeItem
441 for (int i=0;i<=TIactiveFlags.size()-1;i++)
443 if (!standardFlags->isActive (TIactiveFlags.at(i) ))
445 Flag *f=standardFlagsMaster->getFlag(TIactiveFlags.at(i));
446 if (f) standardFlags->activate (f);
450 // Remove standard flags no longer active in TreeItem
451 QStringList BOactiveFlags=standardFlags->activeFlagNames();
452 for (int i=0;i<BOactiveFlags.size();++i)
453 if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
455 standardFlags->deactivate (BOactiveFlags.at(i));
459 // Add missing system flags active in TreeItem
460 TIactiveFlags=treeItem->activeSystemFlagNames();
461 for (int i=0;i<TIactiveFlags.size();++i)
463 if (!systemFlags->isActive (TIactiveFlags.at(i) ))
465 Flag *f=systemFlagsMaster->getFlag(TIactiveFlags.at(i));
466 if (f) systemFlags->activate (f);
470 // Remove system flags no longer active in TreeItem
471 BOactiveFlags=systemFlags->activeFlagNames();
472 for (int i=0;i<BOactiveFlags.size();++i)
474 if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
476 systemFlags->deactivate (BOactiveFlags.at(i));
483 void BranchObj::savePosInAngle ()
485 // Save position in angle
486 for (int i=0; i<treeItem->branchCount(); ++i)
487 treeItem->getBranchObjNum(i)->angle=i;
490 void BranchObj::setDefAttr (BranchModification mod)
493 switch (treeItem->depth())
497 setFrameType (FrameObj::Rectangle);
501 setFrameType (FrameObj::NoFrame);
505 setFrameType (FrameObj::NoFrame);
509 setFrameType (FrameObj::NoFrame);
512 setLinkStyle(getDefLinkStyle(treeItem->parent() ));
514 QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
515 font.setPointSize(fontsize);
516 heading->setFont(font );
519 setColor (treeItem->getHeadingColor() );
521 // Also set styles for children
522 for (int i=0; i<treeItem->branchCount(); ++i)
523 treeItem->getBranchObjNum(i)->setDefAttr(MovedBranch);
527 void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
529 qreal th = bboxTotal.height();
530 int depth=treeItem->depth(); // FIXME-3 needed to recursively calc depth?
534 QString h=QString (depth,' ');
535 h+=treeItem->getHeading();
538 QPointF pp; if (parObj) pp=parObj->getChildPos();
539 cout << "BO::alignRelTo ";
540 cout<<h.toStdString();
541 cout << " d="<<depth<<
542 //cout<< " ref="<<ref<<
543 " bbox.tL="<<bboxTotal.topLeft()<<
547 // " w="<<bbox.width()<<
548 // " h="<<bbox.height()<<
549 // " orient="<<orientation<<
550 // " alignSelf="<<alignSelf<<
551 // " scrolled="<<((BranchItem*)treeItem)->isScrolled()<<
552 // " pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
553 // " hidden="<<hidden<<
559 //updateLinkGeometry();
561 if (depth==1 && parObj)
563 // Position relatively, if needed
564 //if (useRelPos) move2RelPos (relPos.x(), relPos.y());
566 // Calc angle to mapCenter if I am a mainbranch
567 // needed for reordering the mainbranches clockwise
569 angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ),
570 (int)(y() - parObj->getChildPos().y() ) ) );
574 move2RelPos (getRelPos() );
578 // Align myself depending on orientation and parent, but
579 // only if I am not a mainbranch or mapcenter itself
581 if (anim.isAnimated())
586 LinkableMapObj::Orientation o;
587 o=parObj->getOrientation();
591 case LinkableMapObj::LeftOfCenter:
592 move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
593 //move (ref.x() , ref.y() + (th-bbox.height())/2 );
595 case LinkableMapObj::RightOfCenter:
596 move (ref.x() , ref.y() + (th-bbox.height())/2 );
599 qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
605 if ( ((BranchItem*)treeItem)->isScrolled() ) return;
607 // Set reference point for alignment of children
609 if (orientation==LinkableMapObj::LeftOfCenter)
610 ref2.setX(bbox.topLeft().x() - linkwidth);
612 ref2.setX(bbox.topRight().x() + linkwidth);
615 ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
619 // Align the children depending on reference point
620 for (int i=0; i<treeItem->branchCount(); ++i)
622 if (!treeItem->getBranchNum(i)->isHidden())
624 treeItem->getBranchObjNum(i)->alignRelativeTo (ref2,true);
626 // append next branch below current one
627 ref2.setY(ref2.y() + treeItem->getBranchObjNum(i)->getBBoxSizeWithChildren().height() );
633 void BranchObj::reposition()
636 if (!treeItem->getHeading().isEmpty())
637 cout << "BO::reposition "<<qPrintable(treeItem->getHeading())<<endl;
639 cout << "BO::reposition ???"<<endl;
640 // cout << " orient="<<orientation<<endl;
643 if (treeItem->depth()==0)
645 // only calculate the sizes once. If the deepest LMO
646 // changes its height,
647 // all upper LMOs have to change, too.
648 calcBBoxSizeWithChildren();
649 updateLinkGeometry(); // This update is needed if the scene is resized
650 // due to excessive moving of a FIO
652 alignRelativeTo ( QPointF (absPos.x(),
653 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
654 //FIXME-2 qSort (branch.begin(),branch.end(), isAbove);
655 positionBBox(); // Reposition bbox and contents
658 // This is only important for moving branches:
659 // For editing a branch it isn't called...
660 alignRelativeTo ( QPointF (absPos.x(),
661 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
665 void BranchObj::unsetAllRepositionRequests()
667 repositionRequest=false;
668 for (int i=0; i<treeItem->branchCount(); ++i)
669 treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
673 QRectF BranchObj::getTotalBBox()
677 if ( ((BranchItem*)treeItem)->isScrolled() ) return r;
679 for (int i=0; i<treeItem->branchCount(); ++i)
680 if (!treeItem->getBranchNum(i)->isHidden())
681 r=addBBox(treeItem->getBranchObjNum(i)->getTotalBBox(),r);
683 /* FIXME-3 lots of occurences of treeItem->getBranchObjNum(i) in branchobj.cpp
684 better check if they are not NULL and maybe simplify...
685 (have been NULL at least in calcBBoxSizeWithChilds...)
688 for (int i=0; i<treeItem->imageCount(); ++i)
689 if (!treeItem->isHidden())
690 r=addBBox(treeItem->getImageObjNum(i)->getTotalBBox(),r);
694 QRectF BranchObj::getBBoxSizeWithChildren()
699 ConvexPolygon BranchObj::getBoundingPolygon()
702 if (!pi) //FIXME-3 Testing only
704 pi=scene->addPolygon(MapObj::getBoundingPolygon() );
705 pi->setPen(Qt::NoPen);
706 pi->setBrush( QColor(qrand()%32*8,qrand()%32*8,qrand()%32*8) );
707 pi->setZValue(Z_BBOX);
711 if (treeItem->branchCount()==0 || treeItem->depth()==0)
713 if (pi) pi->setPolygon (MapObj::getBoundingPolygon() );
714 return MapObj::getBoundingPolygon();
717 calcBBoxSizeWithChildren(); //FIXME-3 really needed?
719 p<<bboxTotal.topLeft();
720 p<<bboxTotal.topRight();
721 p<<bboxTotal.bottomRight();
722 p<<bboxTotal.bottomLeft();
723 //cout << "BO::getBP (total) "<<treeItem->getHeadingStd()<<" tL="<<bboxTotal.topLeft()<<" bR="<<bboxTotal.bottomRight()<<endl;
724 //cout << " "<<" tL="<<bbox.topLeft()<<" bR="<<bbox.bottomRight()<<endl;
725 if (pi) pi->setPolygon (p );
729 void BranchObj::calcBBoxSizeWithChildren()
731 // This is initially called only from reposition and
732 // and only for mapcenter. So it won't be
733 // called more than once for a single user
737 // Calculate size of LMO including all children (to align them later)
738 bboxTotal.setX(bbox.x() );
739 bboxTotal.setY(bbox.y() );
741 // if branch is scrolled, ignore children, but still consider floatimages
742 BranchItem *bi=(BranchItem*)treeItem;
743 if ( bi->isScrolled() )
745 bboxTotal.setWidth (bbox.width());
746 bboxTotal.setHeight(bbox.height());
752 bboxTotal.setWidth (0);
753 bboxTotal.setHeight(0);
756 bboxTotal.setX (parObj->x());
757 bboxTotal.setY (parObj->y());
760 bboxTotal.setX (bbox.x());
761 bboxTotal.setY (bbox.y());
768 // Now calculate recursivly
772 for (int i=0; i<treeItem->branchCount(); i++)
774 if (!bi->getBranchNum(i)->isHidden())
776 bi->getBranchObjNum(i)->calcBBoxSizeWithChildren();
777 br=bi->getBranchObjNum(i)->getBBoxSizeWithChildren();
778 r.setWidth( max (br.width(), r.width() ));
779 r.setHeight(br.height() + r.height() );
780 if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
781 if (br.x()<bboxTotal.x()) bboxTotal.setX(br.x());
784 // Add myself and also
785 // add width of link to sum if necessary
786 if (bi->branchCount()<1)
787 bboxTotal.setWidth (bbox.width() + r.width() );
789 bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
791 bboxTotal.setHeight(max (r.height(), bbox.height()));
794 QString BranchObj::getSelectString()
796 VymModel *model=treeItem->getModel();
798 return model->getSelectString (this);
803 void BranchObj::setAnimation(const AnimPoint &ap)
808 bool BranchObj::animate()
811 if ( anim.isAnimated() )
816 parObj->reposition(); // we might have been relinked meanwhile