5 #include "attributeitem.h"
6 #include "branchitem.h"
8 #include "mainwindow.h"
12 extern FlagRowMaster *standardFlagsMaster;
13 extern FlagRowMaster *userFlagsMaster;
14 extern FlagRowMaster *systemFlagsMaster;
16 extern bool usingDarkTheme;
18 /////////////////////////////////////////////////////////////////
20 /////////////////////////////////////////////////////////////////
22 BranchObj::BranchObj(QGraphicsItem *parent, TreeItem *ti)
23 : OrnamentedObj(parent, ti)
25 // qDebug ()<< "Const BranchObj (s,ti) ti="<<ti;
27 BranchItem *pi = (BranchItem *)(ti->parent());
28 if (pi && pi != ti->getModel()->getRootItem())
29 parObj = pi->getLMO();
35 BranchObj::~BranchObj()
37 // qDebug()<< "Destr BranchObj of "<<this;
39 // If I'm animated, I need to un-animate myself first
40 if (anim.isAnimated()) {
41 anim.setAnimated(false);
42 VymModel *model = treeItem->getModel();
43 model->stopAnimation(this);
49 void BranchObj::init()
52 absPos = parObj->getChildRefPos();
55 void BranchObj::copy(BranchObj *other)
57 OrnamentedObj::copy(other);
59 setVisibility(other->visible);
64 void BranchObj::clear() {}
66 void BranchObj::setParObjTmp(LinkableMapObj *dst, QPointF m, int off)
68 // Temporary link to dst
69 // m is position of mouse pointer
70 // offset 0: default 1: below dst -1 above dst (if possible)
72 BranchItem *dsti = (BranchItem *)(dst->getTreeItem());
74 BranchItem *pi = (BranchItem *)(dsti->parent());
75 int pi_depth = pi->depth();
76 BranchObj *bodst = (BranchObj *)dst;
80 parObjTmpBuf = parObj;
91 setLinkStyle(dst->getDefLinkStyle(dsti));
93 // Move temporary to new position at destination
94 // Usually the positioning would be done by reposition(),
95 // but then also the destination branch would "Jump" around...
96 // Better just do it approximately
97 if (dsti->depth() == 0) { // new parent is a mapcenter
98 Vector v = (m - bodst->getChildRefPos());
101 move2RelPos(v.toQPointF());
106 // Below is needed e.g. in a freshly loaded map,
107 // bboxTotal seems not to be correct yet
108 // relinking positions too far below then
109 calcBBoxSizeWithChildren();
111 // new parent is just a branch, link to it
112 bodst->calcBBoxSizeWithChildren();
113 QRectF t = bodst->getTotalBBox();
114 if (dsti->getLastBranch())
115 // Move below children of destination
116 y = t.y() + t.height();
118 // Move left or right to destination
123 // we want to link above dst
124 y = bodst->y() - height() + 12;
126 // we want to link below dst
127 // Bottom of sel should be 5 pixels above
128 // the bottom of the branch _below_ the target:
129 // Don't try to find that branch, guess 12 pixels
130 y = bodst->getChildRefPos().y() - height() + 12;
132 if (bodst->getOrientation() == LinkableMapObj::LeftOfCenter)
133 move(bodst->getChildRefPos().x() - linkwidth - bboxTotal.width(),
136 move(bodst->getChildRefPos().x() + linkwidth, y);
139 // updateLinkGeometry is called implicitly in move
143 void BranchObj::unsetParObjTmp()
148 parObj = parObjTmpBuf;
150 setLinkStyle(getDefLinkStyle(treeItem->parent()));
151 updateLinkGeometry();
155 void BranchObj::setVisibility(bool v, int toDepth)
157 BranchItem *bi = (BranchItem *)treeItem;
158 if (bi->depth() <= toDepth) {
159 frame->setVisibility(v);
160 heading->setVisibility(v);
161 systemFlagRowObj->setVisibility(v);
162 standardFlagRowObj->setVisibility(v);
163 LinkableMapObj::setVisibility(v);
165 for (i = 0; i < treeItem->imageCount(); ++i)
166 treeItem->getImageObjNum(i)->setVisibility(v);
167 for (i = 0; i < treeItem->xlinkCount(); ++i)
168 treeItem->getXLinkObjNum(i)->setVisibility();
170 // Only change children, if I am not scrolled
171 if (!bi->isScrolled() && (bi->depth() < toDepth)) {
172 // Now go recursivly through all children
173 for (i = 0; i < treeItem->branchCount(); ++i)
174 treeItem->getBranchObjNum(i)->setVisibility(v, toDepth);
179 void BranchObj::setVisibility(bool v) { setVisibility(v, MAX_DEPTH); }
181 void BranchObj::positionContents()
183 OrnamentedObj::positionContents();
184 updateLinkGeometry(); // required before positioning images
185 for (int i = 0; i < treeItem->imageCount(); ++i)
186 treeItem->getImageObjNum(i)->reposition();
189 void BranchObj::move(double x, double y) { OrnamentedObj::move(x, y); }
191 void BranchObj::move(QPointF p) { move(p.x(), p.y()); }
193 void BranchObj::moveBy(double x, double y)
195 OrnamentedObj::moveBy(x, y);
196 for (int i = 0; i < treeItem->branchCount(); ++i)
197 treeItem->getBranchObjNum(i)->moveBy(x, y);
201 void BranchObj::moveBy(QPointF p) { moveBy(p.x(), p.y()); }
203 void BranchObj::positionBBox() // FIXME-3 consider dimensions of frame
204 // (thickness, geometry, padding...
206 QPointF ap = getAbsPos();
207 bbox.moveTopLeft(ap);
208 positionContents(); // this positions FIOs
210 // Update links to other branches
212 for (int i = 0; i < treeItem->xlinkCount(); ++i) {
213 xlo = treeItem->getXLinkObjNum(i);
219 void BranchObj::calcBBoxSize()
221 QSizeF heading_r = heading->getSize();
222 qreal heading_w = (qreal)heading_r.width();
223 qreal heading_h = (qreal)heading_r.height();
224 QSizeF sysflags_r = systemFlagRowObj->getSize();
225 qreal sysflags_h = sysflags_r.height();
226 qreal sysflags_w = sysflags_r.width();
227 QSizeF stanflags_r = standardFlagRowObj->getSize();
228 qreal stanflags_h = stanflags_r.height();
229 qreal stanflags_w = stanflags_r.width();
233 // set width to sum of all widths
234 w = heading_w + sysflags_w + stanflags_w;
236 // set height to maximum needed height
237 h = max(sysflags_h, stanflags_h);
238 h = max(h, heading_h);
240 // Save the dimension of flags and heading
241 ornamentsBBox.setSize(QSizeF(w, h));
243 // clickBox includes Flags and Heading
244 clickPoly = QPolygonF(ornamentsBBox);
249 topPad = botPad = leftPad = rightPad = 0;
250 bool incV = ((BranchItem *)treeItem)->getIncludeImagesVer();
251 bool incH = ((BranchItem *)treeItem)->getIncludeImagesHor();
254 for (int i = 0; i < treeItem->imageCount(); ++i) {
255 fio = treeItem->getImageObjNum(i);
256 rp = fio->getRelPos();
260 y = rp.y() + fio->height() / 2 - ornamentsBBox.height() / 2;
261 botPad = max(botPad, y);
264 y = -rp.y() + fio->height() / 2 -
265 ornamentsBBox.height() / 2;
266 topPad = max(topPad, y);
272 x = rp.x() + fio->width() / 2 - ornamentsBBox.width() / 2;
273 rightPad = max(rightPad, x);
276 x = -rp.x() + fio->width() / 2 - ornamentsBBox.width() / 2;
277 leftPad = max(leftPad, x);
281 h += topPad + botPad;
282 w += leftPad + rightPad;
286 w += frame->getTotalPadding() * 2;
287 h += frame->getTotalPadding() * 2;
290 bbox.setSize(QSizeF(w, h));
291 // if (debug) qDebug()<<"BO: calcBBox "<<treeItem->getHeading()<<"
295 void BranchObj::setDockPos()
297 floatRefPos = ornamentsBBox.center();
299 if (treeItem->getType() == TreeItem::MapCenter) {
300 // set childRefPos to middle of MapCenterObj
301 QRectF r = clickPoly.boundingRect();
302 childRefPos.setX(r.topLeft().x() + r.width() / 2);
303 childRefPos.setY(r.topLeft().y() + r.height() / 2);
304 parPos = childRefPos;
305 for (int i = 0; i < treeItem->branchCount(); ++i)
306 treeItem->getBranchObjNum(i)->updateLinkGeometry();
309 if (orientation == LinkableMapObj::LeftOfCenter) {
311 if (((BranchItem *)treeItem)->getFrameIncludeChildren()) {
312 childRefPos = QPointF(ornamentsBBox.bottomLeft().x() - leftPad,
314 parPos = QPointF(bboxTotal.bottomRight().x() -
315 frame->getPadding() / 2,
319 childRefPos = QPointF(ornamentsBBox.bottomLeft().x() -
322 parPos = QPointF(ornamentsBBox.bottomRight().x(), bottomlineY);
327 if (((BranchItem *)treeItem)->getFrameIncludeChildren()) {
328 childRefPos = QPointF(
329 ornamentsBBox.bottomRight().x() + rightPad, bottomlineY);
330 parPos = QPointF(bboxTotal.bottomLeft().x() +
331 frame->getPadding() / 2,
335 childRefPos = QPointF(ornamentsBBox.bottomRight().x() +
338 parPos = QPointF(ornamentsBBox.bottomLeft().x(), bottomlineY);
344 void BranchObj::updateVisuals()
347 qWarning("BranchObj::udpateHeading treeItem==NULL");
350 QString s = treeItem->getHeadingText();
351 if (s != heading->text())
354 // Update standard flags active in TreeItem
355 QList<QUuid> TIactiveFlagUids = treeItem->activeFlagUids();
356 standardFlagRowObj->updateActiveFlagObjs(
357 TIactiveFlagUids, standardFlagsMaster, userFlagsMaster);
359 // Add missing system flags active in TreeItem
360 TIactiveFlagUids = treeItem->activeSystemFlagUids();
361 systemFlagRowObj->updateActiveFlagObjs(TIactiveFlagUids, systemFlagsMaster);
366 void BranchObj::setDefAttr(BranchModification mod, bool keepFrame)
369 // Note: not needed in 3.x.0 versions,
370 // where MapDesign will be used
371 QFont font = treeItem->getModel()->getMapDefaultFont();
372 qreal fontsize = font.pointSizeF();
373 switch (treeItem->depth()) {
377 fontsize = fontsize - 2;
380 fontsize = fontsize - 4;
383 fontsize = fontsize - 6;
386 setLinkStyle(getDefLinkStyle(treeItem->parent()));
388 font.setPointSizeF(fontsize);
389 heading->setFont(font);
391 if (mod == NewBranch && !keepFrame) {
392 if (treeItem->depth() == 0) {
393 setFrameType(FrameObj::RoundedRectangle);
394 setFrameBorderWidth(2);
395 if (usingDarkTheme) {
396 setFramePenColor(QColor(Qt::white));
397 setFrameBrushColor(QColor(85, 85, 127));
398 treeItem->setHeadingColor(QColor(Qt::white));
400 setFramePenColor(QColor(Qt::black));
401 setFrameBrushColor(QColor(Qt::white));
404 setFrameType(FrameObj::NoFrame);
406 if (mod == NewBranch)
407 setColor(treeItem->getHeadingColor());
409 // Relinked mapcenters
410 if (!keepFrame && getFrameType() != FrameObj::NoFrame)
411 setFrameType(FrameObj::NoFrame);
413 // Also set styles for children
414 for (int i = 0; i < treeItem->branchCount(); ++i)
415 treeItem->getBranchObjNum(i)->setDefAttr(MovedBranch, keepFrame);
420 void BranchObj::alignRelativeTo(QPointF ref, bool alignSelf)
422 // Define some heights
423 qreal th = bboxTotal.height();
424 qreal ch = 0; // Sum of childrens heights
425 for (int i = 0; i < treeItem->branchCount(); ++i)
426 ch += treeItem->getBranchObjNum(i)->getTotalBBox().height();
429 BranchItem::LayoutHint layoutHint = BranchItem::AutoPositioning;
431 TreeItem *pi = parObj->getTreeItem();
432 depth = 1 + pi->depth();
434 ((BranchItem *)treeItem)->parentBranch()->getChildrenLayout();
437 // set useRelPos, depending on layout
439 if (layoutHint == BranchItem::FreePositioning) {
442 // if we used relPos before, set known positions
443 // "known" means any position != (0,0)
444 if (relPos == QPointF(0, 0))
445 // use current position to get relPos()
460 case UndefinedOrientation: o = "UndefOrientation"; break;
461 case LeftOfCenter: o = "LeftOfCenter"; break;
462 case RightOfCenter: o = "RightOfCenter"; break;
465 QString h=QString (depth+1,' ');
466 h += treeItem->getHeadingPlain();
467 h += QString (25,' ');
470 if (parObj) pp = parObj->getChildRefPos();
471 qDebug() << "BO::alignRelTo for "<<h
472 // qDebug() << " d="<<depth;
473 // qDebug() <<" ref="<<ref;
474 // qDebug() <<" th="<<th;
475 // qDebug() <<" ch="<<ch;
476 // if (ch < th) qDebug()<<" ch<th !";
477 // qDebug() <<" parO="<<parObj;
478 //qDebug() << " bbox.tL="<<bboxTotal.topLeft();
479 << " useRelPos=" << useRelPos
480 << " layoutHint= " << layoutHint
481 // qDebug() <<"absPos="<<absPos
482 << " relPos="<<relPos
485 << " orient="<<o<<" "<<orientation;
486 // << " alignSelf="<<alignSelf
487 // << " scrolled="<<((BranchItem*)treeItem)->isScrolled()
488 // << " pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad
489 // << " hidden="<<hidden
499 move(getAbsPos()); // Trigger update of frames etc.
501 move2RelPos(getRelPos());
502 else if (depth > 1) {
503 if (layoutHint == BranchItem::FreePositioning)
504 move2RelPos(getRelPos());
506 if (anim.isAnimated())
510 switch (orientation) {
511 case LinkableMapObj::LeftOfCenter:
512 move(ref.x() - bbox.width(),
513 ref.y() + (th - bbox.height()) / 2);
515 case LinkableMapObj::RightOfCenter:
516 move(ref.x(), ref.y() + (th - bbox.height()) / 2);
519 qWarning("LMO::alignRelativeTo: oops, no orientation "
527 // Without ancestors I am done
528 if (((BranchItem *)treeItem)->isScrolled())
531 // Set reference point for alignment of children
533 if (orientation == LinkableMapObj::LeftOfCenter)
534 ref2.setX(childRefPos.x() - linkwidth);
536 ref2.setX(childRefPos.x() + linkwidth);
539 ref2.setY(absPos.y() + (bbox.height() - ch) / 2);
542 ref2.setY(ref.y() + frame->getPadding());
544 // Parent is bigger than all of childs, center childs vertically
545 ref2.setY(ref.y() + (th - ch) / 2);
548 // Align the branch children depending on reference point
549 for (int i = 0; i < treeItem->branchCount(); ++i) {
550 if (!treeItem->getBranchNum(i)->isHidden()) {
551 treeItem->getBranchObjNum(i)->alignRelativeTo(ref2, true);
553 // append next branch below current one
555 treeItem->getBranchObjNum(i)->getTotalBBox().height());
560 void BranchObj::reposition()
565 if (!treeItem->getHeading().isEmpty())
566 qDebug()<< " BO::reposition a) d="<<treeItem->depth()<<"
567 "<<treeItem->getHeading(); else qDebug()<< " BO::reposition a)
568 d="<<treeItem->depth()<<" ???";
572 if (treeItem->depth() == 0)
573 // only calculate the sizes once. If the deepest LMO
574 // changes its height,
575 // all upper LMOs have to change, too.
576 calcBBoxSizeWithChildren();
578 alignRelativeTo(QPointF(
579 absPos.x(), absPos.y() - (bboxTotal.height() - bbox.height()) / 2));
582 void BranchObj::unsetAllRepositionRequests()
584 repositionRequest = false;
585 for (int i = 0; i < treeItem->branchCount(); ++i)
586 treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
589 QRectF BranchObj::getTotalBBox() { return bboxTotal; }
591 ConvexPolygon BranchObj::getBoundingPolygon()
593 if (treeItem->branchCount() == 0 || treeItem->depth() == 0) {
594 return MapObj::getBoundingPolygon();
598 p << bboxTotal.topLeft();
599 p << bboxTotal.topRight();
600 p << bboxTotal.bottomRight();
601 p << bboxTotal.bottomLeft();
605 void BranchObj::calcBBoxSizeWithChildren()
607 // if branch is scrolled, ignore children, but still consider floatimages
608 BranchItem *bi = (BranchItem *)treeItem;
609 if (bi->isScrolled()) {
610 bboxTotal.setWidth(bbox.width());
611 bboxTotal.setHeight(bbox.height());
615 if (bi->isHidden()) {
616 bboxTotal.setWidth(0);
617 bboxTotal.setHeight(0);
621 QRectF r(0, 0, 0, 0);
628 for (int i = 0; i < treeItem->branchCount(); i++) {
629 if (!bi->getBranchNum(i)->isHidden()) {
630 BranchObj *bo = bi->getBranchObjNum(i);
631 bo->calcBBoxSizeWithChildren();
632 br = bo->getTotalBBox();
633 r.setWidth(max(br.width(), r.width()));
634 r.setHeight(br.height() + r.height());
638 // Add myself and also
639 // add width of link to sum if necessary
640 if (bi->branchCount() < 1)
641 bboxTotal.setWidth(bbox.width() + r.width());
643 bboxTotal.setWidth(bbox.width() + r.width() + linkwidth);
645 // bbox already contains frame->padding()*2
647 max(r.height() + frame->getPadding() * 2, bbox.height()));
650 void BranchObj::setAnimation(const AnimPoint &ap) { anim = ap; }
652 void BranchObj::stopAnimation()
661 bool BranchObj::animate()
664 if (anim.isAnimated()) {