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* lmo, QPointF m, int off)
120 // Temporary link to lmo
121 // m is position of mouse pointer
122 // offset 0: default 1: below lmo -1 above lmo (if possible)
124 BranchItem *pi=(BranchItem*)(lmo->getTreeItem()->parent());
125 int pi_depth=pi->depth();
126 BranchObj* o=(BranchObj*)(lmo);
130 // ignore mapcenter and mainbranch //FIXME-3 MCO meanwhile also could be relinked
131 if (pi_depth<2) off=0;
138 // setLinkStyle calls updateLinkGeometry, only set it once
139 //LinkableMapObj::Style ls=getDefLinkStyle (lmo->getTreeItem() );
140 //if (style!=ls ) setLinkStyle (ls);
141 setLinkStyle (lmo->getDefLinkStyle (lmo->getTreeItem()));
143 // Move temporary to new position at destination
144 // Usually the positioning would be done by reposition(),
145 // but then also the destination branch would "Jump" around...
146 // Better just do it approximately
147 if (parObj->getTreeItem()->depth()==0)
148 { // new parent is a mapcenter
150 //FIXME-2 rewrite to us new normalize QPointF p= normalize ( QPointF (m.x() - o->getChildPos().x(),
151 // m.y() - o->getChildPos().y() ));
152 QPointF p= ( QPointF (m.x() - o->getChildPos().x(),
153 m.y() - o->getChildPos().y() ));
154 if (p.x()<0) p.setX( p.x()-bbox.width() );
161 // new parent is just a branch, link to it
162 QRectF t=o->getBBoxSizeWithChildren();
163 if (o->getTreeItem()->getLastBranch())
164 y=t.y() + t.height() ;
171 // we want to link above lmo
172 y=o->y() - height() + 5;
174 // we want to link below lmo
175 // Bottom of sel should be 5 pixels above
176 // the bottom of the branch _below_ the target:
177 // Don't try to find that branch, guess 12 pixels
178 y=o->getChildPos().y() -height() + 12;
180 if (o->getOrientation()==LinkableMapObj::LeftOfCenter)
181 move ( o->getChildPos().x() - linkwidth, y );
183 move (o->getChildPos().x() + linkwidth, y );
186 // updateLinkGeometry is called implicitly in move
190 void BranchObj::unsetParObjTmp()
197 setLinkStyle (getDefLinkStyle(treeItem->parent() ) );
198 updateLinkGeometry();
202 void BranchObj::setVisibility(bool v, int toDepth)
204 BranchItem *bi=(BranchItem*)treeItem;
205 if (bi->depth() <= toDepth)
207 frame->setVisibility(v);
208 heading->setVisibility(v);
209 systemFlags->setVisibility(v);
210 standardFlags->setVisibility(v);
211 LinkableMapObj::setVisibility (v);
213 for (i=0; i<treeItem->imageCount(); ++i)
214 treeItem->getImageObjNum(i)->setVisibility (v);
215 for (i=0; i<treeItem->xlinkCount(); ++i)
216 treeItem->getXLinkObjNum(i)->setVisibility ();
218 // Only change children, if I am not scrolled
219 if (! bi->isScrolled() && (bi->depth() < toDepth))
221 // Now go recursivly through all children //FIXME-3 are there multiple calls for lower level items???
222 for (i=0; i<treeItem->branchCount(); ++i)
223 treeItem->getBranchObjNum(i)->setVisibility (v,toDepth);
225 } // depth <= toDepth
229 void BranchObj::setVisibility(bool v)
231 setVisibility (v,MAX_DEPTH);
235 void BranchObj::setLinkColor ()
237 // Overloaded from LinkableMapObj
238 // BranchObj can use color of heading
240 VymModel *model=treeItem->getModel();
243 if (model->getMapLinkColorHint()==HeadingColor)
244 LinkableMapObj::setLinkColor (heading->getColor() );
246 LinkableMapObj::setLinkColor ();
250 void BranchObj::updateContentSize()
257 void BranchObj::positionContents()
259 for (int i=0; i<treeItem->imageCount(); ++i)
260 treeItem->getImageObjNum(i)->reposition();
261 OrnamentedObj::positionContents();
264 void BranchObj::move (double x, double y)
266 OrnamentedObj::move (x,y);
268 for (int i=0; i<treeItem->imageCount(); ++i )
270 fio=treeItem->getImageObjNum(i);
271 if (fio) fio->reposition();
276 void BranchObj::move (QPointF p)
281 void BranchObj::moveBy (double x, double y)
283 OrnamentedObj::moveBy (x,y);
284 for (int i=0; i<treeItem->branchCount(); ++i)
285 treeItem->getBranchObjNum(i)->moveBy (x,y);
289 void BranchObj::moveBy (QPointF p)
291 moveBy (p.x(), p.y());
295 void BranchObj::positionBBox()
297 QPointF ap=getAbsPos();
298 bbox.moveTopLeft (ap);
302 frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
304 //Update links to other branches
306 for (int i=0; i<treeItem->xlinkCount(); ++i)
308 xlo=treeItem->getXLinkObjNum(i);
309 if (xlo) xlo->updateXLink();
313 void BranchObj::calcBBoxSize()
315 QSizeF heading_r=heading->getSize();
316 qreal heading_w=(qreal) heading_r.width() ;
317 qreal heading_h=(qreal) heading_r.height() ;
318 QSizeF sysflags_r=systemFlags->getSize();
319 qreal sysflags_h=sysflags_r.height();
320 qreal sysflags_w=sysflags_r.width();
321 QSizeF stanflags_r=standardFlags->getSize();
322 qreal stanflags_h=stanflags_r.height();
323 qreal stanflags_w=stanflags_r.width();
327 // set width to sum of all widths
328 w=heading_w + sysflags_w + stanflags_w;
329 // set height to maximum needed height
330 h=max (sysflags_h,stanflags_h);
333 // Save the dimension of flags and heading
334 ornamentsBBox.setSize ( QSizeF(w,h));
336 // clickBox includes Flags and Heading
337 clickBox.setSize (ornamentsBBox.size() );
342 topPad=botPad=leftPad=rightPad=0;
343 bool incV=((BranchItem*)treeItem)->getIncludeImagesVer();
344 bool incH=((BranchItem*)treeItem)->getIncludeImagesHor();
348 for (int i=0; i<treeItem->imageCount(); ++i )
350 fio=treeItem->getImageObjNum(i);
355 topPad=max (topPad,-rp.y()-h);
356 if (rp.y()+fio->height() > 0)
357 botPad=max (botPad,rp.y()+fio->height());
361 if (orientation==LinkableMapObj::RightOfCenter)
364 leftPad=max (leftPad,-rp.x()-w);
365 if (rp.x()+fio->width() > 0)
366 rightPad=max (rightPad,rp.x()+fio->width());
370 leftPad=max (leftPad,-rp.x());
371 if (rp.x()+fio->width() > w)
372 rightPad=max (rightPad,rp.x()+fio->width()-w);
381 w+=frame->getPadding();
382 h+=frame->getPadding();
385 bbox.setSize (QSizeF (w,h));
388 void BranchObj::setDockPos()
390 if (treeItem->getType()==TreeItem::MapCenter)
392 // set childPos to middle of MapCenterObj
393 childPos.setX( clickBox.topLeft().x() + clickBox.width()/2 );
394 childPos.setY( clickBox.topLeft().y() + clickBox.height()/2 );
396 for (int i=0; i<treeItem->branchCount(); ++i)
397 treeItem->getBranchObjNum(i)->updateLinkGeometry();
401 // Sets childpos and parpos depending on orientation
402 if (getOrientation()==LinkableMapObj::LeftOfCenter )
405 ornamentsBBox.bottomLeft().x(),
408 ornamentsBBox.bottomRight().x(),
413 ornamentsBBox.bottomRight().x(),
416 ornamentsBBox.bottomLeft().x(),
422 void BranchObj::updateData()
427 qWarning ("BranchObj::udpateHeading treeItem==NULL");
430 QString s=treeItem->getHeading();
431 if (s!=heading->text())
433 heading->setText (s);
436 QStringList TIactiveFlags=treeItem->activeStandardFlagNames();
438 // Add missing standard flags active in TreeItem
439 for (int i=0;i<=TIactiveFlags.size()-1;i++)
441 if (!standardFlags->isActive (TIactiveFlags.at(i) ))
443 Flag *f=standardFlagsMaster->getFlag(TIactiveFlags.at(i));
444 if (f) standardFlags->activate (f);
448 // Remove standard flags no longer active in TreeItem
449 QStringList BOactiveFlags=standardFlags->activeFlagNames();
450 for (int i=0;i<BOactiveFlags.size();++i)
451 if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
453 standardFlags->deactivate (BOactiveFlags.at(i));
457 // Add missing system flags active in TreeItem
458 TIactiveFlags=treeItem->activeSystemFlagNames();
459 for (int i=0;i<TIactiveFlags.size();++i)
461 if (!systemFlags->isActive (TIactiveFlags.at(i) ))
463 Flag *f=systemFlagsMaster->getFlag(TIactiveFlags.at(i));
464 if (f) systemFlags->activate (f);
468 // Remove system flags no longer active in TreeItem
469 BOactiveFlags=systemFlags->activeFlagNames();
470 for (int i=0;i<BOactiveFlags.size();++i)
472 if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
474 systemFlags->deactivate (BOactiveFlags.at(i));
481 void BranchObj::savePosInAngle ()
483 // Save position in angle
484 for (int i=0; i<treeItem->branchCount(); ++i)
485 treeItem->getBranchObjNum(i)->angle=i;
488 void BranchObj::setDefAttr (BranchModification mod)
491 switch (treeItem->depth())
493 case 0: fontsize=16; break;
494 case 1: fontsize=12; break;
495 default: fontsize=10; break;
497 setLinkStyle(getDefLinkStyle(treeItem->parent() ));
499 QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
500 font.setPointSize(fontsize);
501 heading->setFont(font );
504 setColor (treeItem->getHeadingColor() );
508 void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
510 qreal th = bboxTotal.height();
511 int depth=treeItem->depth(); // FIXME-3 needed to recursively calc depth?
515 QString h=QString (depth,' ');
516 h+=treeItem->getHeading();
519 QPointF pp; if (parObj) pp=parObj->getChildPos();
520 cout << "BO::alignRelTo ";
521 cout<<h.toStdString();
522 cout << " d="<<depth<<
523 //cout<< " ref="<<ref<<
524 " bbox.tL="<<bboxTotal.topLeft()<<
528 // " w="<<bbox.width()<<
529 // " h="<<bbox.height()<<
530 // " orient="<<orientation<<
531 // " alignSelf="<<alignSelf<<
532 // " scrolled="<<((BranchItem*)treeItem)->isScrolled()<<
533 // " pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
534 // " hidden="<<hidden<<
540 //updateLinkGeometry();
542 if (depth==1 && parObj)
544 // Position relatively, if needed
545 //if (useRelPos) move2RelPos (relPos.x(), relPos.y());
547 // Calc angle to mapCenter if I am a mainbranch
548 // needed for reordering the mainbranches clockwise
550 angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ),
551 (int)(y() - parObj->getChildPos().y() ) ) );
555 // Align myself depending on orientation and parent, but
556 // only if I am not a mainbranch or mapcenter itself
558 if (anim.isAnimated())
563 LinkableMapObj::Orientation o;
564 o=parObj->getOrientation();
568 case LinkableMapObj::LeftOfCenter:
569 move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
570 //move (ref.x() , ref.y() + (th-bbox.height())/2 );
572 case LinkableMapObj::RightOfCenter:
573 move (ref.x() , ref.y() + (th-bbox.height())/2 );
576 qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
582 if ( ((BranchItem*)treeItem)->isScrolled() ) return;
584 // Set reference point for alignment of children
586 if (orientation==LinkableMapObj::LeftOfCenter)
587 ref2.setX(bbox.topLeft().x() - linkwidth);
589 ref2.setX(bbox.topRight().x() + linkwidth);
592 ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
596 // Align the children depending on reference point
597 for (int i=0; i<treeItem->branchCount(); ++i)
599 if (!treeItem->getBranchNum(i)->isHidden())
601 treeItem->getBranchObjNum(i)->alignRelativeTo (ref2,true);
603 // append next branch below current one
604 ref2.setY(ref2.y() + treeItem->getBranchObjNum(i)->getBBoxSizeWithChildren().height() );
610 void BranchObj::reposition()
613 if (!treeItem->getHeading().isEmpty())
614 cout << "BO::reposition "<<qPrintable(treeItem->getHeading())<<endl;
616 cout << "BO::reposition ???"<<endl;
617 // cout << " orient="<<orientation<<endl;
620 if (treeItem->depth()==0)
622 // only calculate the sizes once. If the deepest LMO
623 // changes its height,
624 // all upper LMOs have to change, too.
625 calcBBoxSizeWithChildren();
626 updateLinkGeometry(); // This update is needed if the scene is resized
627 // due to excessive moving of a FIO
629 alignRelativeTo ( QPointF (absPos.x(),
630 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
631 //FIXME-2 qSort (branch.begin(),branch.end(), isAbove);
632 positionBBox(); // Reposition bbox and contents
635 // This is only important for moving branches:
636 // For editing a branch it isn't called...
637 alignRelativeTo ( QPointF (absPos.x(),
638 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
642 void BranchObj::unsetAllRepositionRequests()
644 repositionRequest=false;
645 for (int i=0; i<treeItem->branchCount(); ++i)
646 treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
650 QPolygonF BranchObj::shape()
654 QRectF r=getTotalBBox();
655 if (orientation==LinkableMapObj::LeftOfCenter)
658 <<QPointF (bbox.topLeft().x(), r.topLeft().y() )
661 <<QPointF (bbox.bottomLeft().x(), r.bottomLeft().y() ) ;
665 <<QPointF (bbox.topRight().x(), r.topRight().y() )
668 <<QPointF (bbox.bottomRight().x(), r.bottomRight().y() ) ;
672 QRectF BranchObj::getTotalBBox()
676 if ( ((BranchItem*)treeItem)->isScrolled() ) return r;
678 for (int i=0; i<treeItem->branchCount(); ++i)
679 if (!treeItem->getBranchNum(i)->isHidden())
680 r=addBBox(treeItem->getBranchObjNum(i)->getTotalBBox(),r);
682 /* FIXME-3 lots of occurences of treeItem->getBranchObjNum(i) in branchobj.cpp
683 better check if they are not NULL and maybe simplify...
684 (have been NULL at least in calcBBoxSizeWithChilds...)
687 for (int i=0; i<treeItem->imageCount(); ++i)
688 if (!treeItem->isHidden())
689 r=addBBox(treeItem->getImageObjNum(i)->getTotalBBox(),r);
693 QRectF BranchObj::getBBoxSizeWithChildren()
698 ConvexPolygon BranchObj::getBoundingPolygon()
701 if (!pi) //FIXME-3 Testing only
703 pi=scene->addPolygon(MapObj::getBoundingPolygon() );
704 pi->setPen(Qt::NoPen);
705 pi->setBrush( QColor(qrand()%32*8,qrand()%32*8,qrand()%32*8) );
706 pi->setZValue(Z_BBOX);
709 if (treeItem->branchCount()==0 || treeItem->depth()==0)
711 if (pi) pi->setPolygon (MapObj::getBoundingPolygon() );
712 return MapObj::getBoundingPolygon();
715 calcBBoxSizeWithChildren(); //FIXME-3 really needed?
717 p<<bboxTotal.topLeft();
718 p<<bboxTotal.topRight();
719 p<<bboxTotal.bottomRight();
720 p<<bboxTotal.bottomLeft();
721 if (pi) pi->setPolygon (p );
725 void BranchObj::calcBBoxSizeWithChildren()
727 // This is initially called only from reposition and
728 // and only for mapcenter. So it won't be
729 // called more than once for a single user
733 // Calculate size of LMO including all children (to align them later)
734 bboxTotal.setX(bbox.x() );
735 bboxTotal.setY(bbox.y() );
737 // if branch is scrolled, ignore children, but still consider floatimages
738 BranchItem *bi=(BranchItem*)treeItem;
739 if ( bi->isScrolled() )
741 bboxTotal.setWidth (bbox.width());
742 bboxTotal.setHeight(bbox.height());
748 bboxTotal.setWidth (0);
749 bboxTotal.setHeight(0);
752 bboxTotal.setX (parObj->x());
753 bboxTotal.setY (parObj->y());
756 bboxTotal.setX (bbox.x());
757 bboxTotal.setY (bbox.y());
764 // Now calculate recursivly
768 for (int i=0; i<treeItem->branchCount(); i++)
770 if (!bi->getBranchNum(i)->isHidden())
772 bi->getBranchObjNum(i)->calcBBoxSizeWithChildren();
773 br=bi->getBranchObjNum(i)->getBBoxSizeWithChildren();
774 r.setWidth( max (br.width(), r.width() ));
775 r.setHeight(br.height() + r.height() );
776 if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
779 // Add myself and also
780 // add width of link to sum if necessary
781 if (bi->branchCount()<1)
782 bboxTotal.setWidth (bbox.width() + r.width() );
784 bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
786 bboxTotal.setHeight(max (r.height(), bbox.height()));
789 QString BranchObj::getSelectString()
791 VymModel *model=treeItem->getModel();
793 return model->getSelectString (this);
798 void BranchObj::setAnimation(const AnimPoint &ap)
803 bool BranchObj::animate()
806 if ( anim.isAnimated() )
811 parObj->reposition(); // we might have been relinked meanwhile