--- /dev/null
+#include "branchitem.h"
+
+#include "attributeitem.h"
+#include "branchobj.h"
+#include "task.h"
+#include "taskmodel.h"
+#include "vymmodel.h"
+#include "xlink.h"
+#include "xlinkitem.h"
+
+extern TaskModel *taskModel;
+
+//#include <QDir>
+
+BranchItem::BranchItem(TreeItem *parent)
+ : MapItem(parent)
+{
+ //qDebug()<< "Constr. BranchItem this=" << this << "parent:" << parent;
+
+ // Set type if parent is known yet
+ // if not, type is set in insertBranch or TreeItem::appendChild
+ if (parent == rootItem)
+ setType(MapCenter);
+ else
+ setType(Branch);
+
+ scrolled = false;
+ tmpUnscrolled = false;
+
+ includeImagesVer = false;
+ includeImagesHor = false;
+ includeChildren = false;
+ childrenLayout = BranchItem::AutoPositioning;
+
+ lastSelectedBranchNum = 0;
+ lastSelectedBranchNumAlt = 0;
+
+ task = NULL;
+}
+
+BranchItem::~BranchItem()
+{
+ // qDebug()<< "Destr. BranchItem this="<<this<<" "<<getHeading();
+ if (mo) {
+ delete mo;
+ mo = NULL;
+ }
+ clear();
+}
+
+void BranchItem::clear()
+{
+ if (task)
+ taskModel->deleteTask(task);
+}
+
+void BranchItem::copy(BranchItem *other) // TODO lacks most of data...
+{
+ scrolled = other->scrolled;
+ tmpUnscrolled = other->tmpUnscrolled;
+}
+
+BranchItem *BranchItem::parentBranch() { return (BranchItem *)parentItem; }
+
+void BranchItem::insertBranch(int pos, BranchItem *branch)
+{
+ if (pos < 0)
+ pos = 0;
+ if (pos > branchCounter)
+ pos = branchCounter;
+ childItems.insert(pos + branchOffset, branch);
+ branch->parentItem = this;
+ branch->rootItem = rootItem;
+ branch->setModel(model);
+ if (parentItem == rootItem)
+ setType(MapCenter);
+ else
+ setType(Branch);
+
+ if (branchCounter == 0)
+ branchOffset = childItems.count() - 1;
+ branchCounter++;
+}
+
+QString BranchItem::saveToDir(const QString &tmpdir, const QString &prefix,
+ const QPointF &offset, QList<Link *> &tmpLinks)
+{
+ // Cloudy stuff can be hidden during exports
+ if (hidden)
+ return QString();
+
+ // Save uuid
+ QString idAttr = attribut("uuid", uuid.toString());
+
+ QString s, a;
+
+ // Update of note is usually done while unselecting a branch
+
+ QString scrolledAttr;
+ if (scrolled)
+ scrolledAttr = attribut("scrolled", "yes");
+ else
+ scrolledAttr = "";
+
+ // save area, if not scrolled // not needed if HTML is rewritten...
+ // also we could check if _any_ of parents is scrolled
+ QString areaAttr;
+ if (mo && parentItem->isBranchLikeType() &&
+ !((BranchItem *)parentItem)->isScrolled()) {
+ qreal x = mo->getAbsPos().x();
+ qreal y = mo->getAbsPos().y();
+ areaAttr =
+ attribut("x1", QString().setNum(x - offset.x())) +
+ attribut("y1", QString().setNum(y - offset.y())) +
+ attribut("x2", QString().setNum(x + mo->width() - offset.x())) +
+ attribut("y2", QString().setNum(y + mo->height() - offset.y()));
+ }
+ else
+ areaAttr = "";
+
+ QString elementName;
+ if (parentItem == rootItem)
+ elementName = "mapcenter";
+ else
+ elementName = "branch";
+
+ // Free positioning of children
+ QString layoutAttr;
+ if (childrenLayout == BranchItem::FreePositioning)
+ layoutAttr += attribut("childrenFreePos", "true");
+
+ // Save rotation
+ QString rotAttr;
+ if (mo && mo->getRotation() != 0)
+ rotAttr = attribut("rotation", QString().setNum(mo->getRotation()));
+
+ s = beginElement(elementName + getMapAttr() + getGeneralAttr() +
+ scrolledAttr + getIncludeImageAttr() + rotAttr +
+ layoutAttr + idAttr);
+ incIndent();
+
+ // save heading
+ s += heading.saveToDir();
+
+ // save note
+ if (!note.isEmpty())
+ s += note.saveToDir();
+
+ // Save frame // not saved if there is no MO
+ if (mo) {
+ // Avoid saving NoFrame for objects other than MapCenter
+ if (depth() == 0 || ((OrnamentedObj *)mo)->getFrame()->getFrameType() !=
+ FrameObj::NoFrame)
+ s += ((OrnamentedObj *)mo)->getFrame()->saveToDir();
+ }
+
+ // save names of flags set
+ s += standardFlags.saveState();
+ s += userFlags.saveState();
+
+ // Save Images
+ for (int i = 0; i < imageCount(); ++i)
+ s += getImageNum(i)->saveToDir(tmpdir, prefix);
+
+ // save attributes
+ for (int i = 0; i < attributeCount(); ++i)
+ s += getAttributeNum(i)->getDataXML();
+
+ // save task
+ if (task)
+ s += task->saveToDir();
+
+ // Save branches
+ int i = 0;
+ TreeItem *ti = getBranchNum(i);
+ while (ti) {
+ s += getBranchNum(i)->saveToDir(tmpdir, prefix, offset, tmpLinks);
+ i++;
+ ti = getBranchNum(i);
+ }
+
+ // Mark Links for save
+ for (int i = 0; i < xlinkCount(); ++i) {
+ Link *l = getXLinkItemNum(i)->getLink();
+ if (l && !tmpLinks.contains(l))
+ tmpLinks.append(l);
+ }
+ decIndent();
+ s += endElement(elementName);
+ return s;
+}
+
+void BranchItem::updateVisibility()
+{
+ // Needed to hide relinked branch, if parent is scrolled
+ if (mo) {
+ if (hasScrolledParent(this) || hidden)
+ mo->setVisibility(false);
+ else
+ mo->setVisibility(true);
+ }
+}
+
+void BranchItem::setHeadingColor(QColor color)
+{
+ TreeItem::setHeadingColor(color);
+ if (mo)
+ ((BranchObj *)mo)->setColor(color);
+}
+
+void BranchItem::updateTaskFlag()
+{
+ systemFlags.deactivateGroup("system-tasks");
+ if (task) {
+ QString s = "system-" + task->getIconString();
+ systemFlags.activate(s);
+ model->emitDataChanged(this);
+ }
+ // else: During initialization the task is not yet attached to branch,
+ // so ignore it for now
+}
+
+void BranchItem::setTask(Task *t)
+{
+ task = t;
+ updateTaskFlag();
+}
+
+Task *BranchItem::getTask() { return task; }
+
+void BranchItem::scroll()
+{
+ if (tmpUnscrolled)
+ resetTmpUnscroll();
+ if (!scrolled)
+ toggleScroll();
+}
+void BranchItem::unScroll()
+{
+ if (tmpUnscrolled)
+ resetTmpUnscroll();
+ if (scrolled)
+ toggleScroll();
+}
+
+bool BranchItem::toggleScroll()
+{
+ // MapCenters are not scrollable
+ if (depth() == 0)
+ return false;
+
+ BranchObj *bo;
+ if (scrolled) {
+ scrolled = false;
+ systemFlags.deactivate(QString("system-scrolledright"));
+ if (branchCounter > 0)
+ for (int i = 0; i < branchCounter; ++i) {
+ bo = (BranchObj *)(getBranchNum(i)->getMO());
+ if (bo)
+ bo->setVisibility(true); // Recursively!
+ }
+ }
+ else {
+ scrolled = true;
+ systemFlags.activate(QString("system-scrolledright"));
+ if (branchCounter > 0)
+ for (int i = 0; i < branchCounter; ++i) {
+ bo = (BranchObj *)(getBranchNum(i)->getMO());
+ if (bo)
+ bo->setVisibility(false); // Recursively!
+ }
+ }
+ return true;
+}
+
+bool BranchItem::isScrolled() { return scrolled; }
+
+bool BranchItem::hasScrolledParent(BranchItem *start)
+{
+ // Calls parents recursivly to
+ // find out, if we are scrolled at all.
+ // But ignore myself, just look at parents.
+
+ if (!start)
+ start = this;
+
+ if (this != start && scrolled)
+ return true;
+
+ BranchItem *bi = (BranchItem *)parentItem;
+ if (bi && bi != rootItem)
+ return bi->hasScrolledParent(start);
+ else
+ return false;
+}
+
+bool BranchItem::tmpUnscroll(BranchItem *start)
+{
+ bool result = false;
+
+ if (!start)
+ start = this;
+
+ // Unscroll parent (recursivly)
+ BranchItem *pi = (BranchItem *)parentItem;
+ if (pi && pi->isBranchLikeType())
+ result = pi->tmpUnscroll(start);
+
+ // Unscroll myself
+ if (start != this && scrolled) {
+ tmpUnscrolled = true;
+ systemFlags.activate(QString("system-tmpUnscrolledRight"));
+ toggleScroll();
+ model->emitDataChanged(this);
+ result = true;
+ }
+ return result;
+}
+
+bool BranchItem::resetTmpUnscroll()
+{
+ bool result = false;
+
+ // Unscroll parent (recursivly)
+ BranchItem *pi = (BranchItem *)parentItem;
+ if (pi && pi->isBranchLikeType())
+ result = pi->resetTmpUnscroll();
+
+ // Unscroll myself
+ if (tmpUnscrolled) {
+ tmpUnscrolled = false;
+ systemFlags.deactivate(QString("system-tmpUnscrolledRight"));
+ toggleScroll();
+ model->emitDataChanged(this);
+ result = true;
+ }
+ return result;
+}
+
+void BranchItem::sortChildren(
+ bool inverse) // FIXME-4 optimize by not using moveUp/Down
+{
+ int childCount = branchCounter;
+ int curChildIndex;
+ bool madeChanges = false;
+ do {
+ madeChanges = false;
+ for (curChildIndex = 1; curChildIndex < childCount; curChildIndex++) {
+ BranchItem *curChild = getBranchNum(curChildIndex);
+ BranchItem *prevChild = getBranchNum(curChildIndex - 1);
+ if (inverse) {
+ if (prevChild->getHeadingPlain().compare(
+ curChild->getHeadingPlain(), Qt::CaseInsensitive) < 0) {
+ model->moveUp(curChild);
+ madeChanges = true;
+ }
+ }
+ else if (prevChild->getHeadingPlain().compare(
+ curChild->getHeadingPlain(), Qt::CaseInsensitive) >
+ 0) {
+ model->moveUp(curChild);
+ madeChanges = true;
+ }
+ }
+ } while (madeChanges);
+}
+
+void BranchItem::setChildrenLayout(BranchItem::LayoutHint layoutHint)
+{
+ childrenLayout = layoutHint;
+}
+
+BranchItem::LayoutHint BranchItem::getChildrenLayout()
+{
+ return childrenLayout;
+}
+
+void BranchItem::setIncludeImagesVer(bool b) { includeImagesVer = b; }
+
+bool BranchItem::getIncludeImagesVer() { return includeImagesVer; }
+
+void BranchItem::setIncludeImagesHor(bool b) { includeImagesHor = b; }
+
+bool BranchItem::getIncludeImagesHor() { return includeImagesHor; }
+
+QString BranchItem::getIncludeImageAttr()
+{
+ QString a;
+ if (includeImagesVer)
+ a = attribut("incImgV", "true");
+ if (includeImagesHor)
+ a += attribut("incImgH", "true");
+ return a;
+}
+
+BranchItem *BranchItem::getFramedParentBranch(BranchItem *start)
+{
+ BranchObj *bo = getBranchObj();
+ if (bo && bo->getFrameType() != FrameObj::NoFrame) {
+ if (bo->getFrame()->getFrameIncludeChildren())
+ return this;
+ if (this == start)
+ return this;
+ }
+ BranchItem *bi = (BranchItem *)parentItem;
+ if (bi && bi != rootItem)
+ return bi->getFramedParentBranch(start);
+ else
+ return NULL;
+}
+
+void BranchItem::setFrameIncludeChildren(bool b)
+{
+ includeChildren = b; // FIXME-4 ugly: same information stored in FrameObj
+ BranchObj *bo = getBranchObj();
+ if (bo)
+ bo->getFrame()->setFrameIncludeChildren(b);
+}
+
+bool BranchItem::getFrameIncludeChildren()
+{
+ BranchObj *bo = getBranchObj();
+ if (bo)
+ return bo->getFrame()->getFrameIncludeChildren();
+ else
+ return includeChildren;
+}
+
+QColor BranchItem::getBackgroundColor(BranchItem *start, bool checkInnerFrame)
+{
+ /*
+ // Determine background color in taskEditor, first try inner frame
+ if (checkInnerFrame && branchContainer->frameType(true) != FrameContainer::NoFrame)
+ return branchContainer->frameBrushColor(true);
+
+ // Outer frame
+ if (branchContainer->frameType(false) != FrameContainer::NoFrame)
+ return branchContainer->frameBrushColor(false);
+
+ BranchItem *pb = parentBranch();
+ if (pb && pb != rootItem)
+ // Recursively try parents and check for frames there
+ return pb->getBackgroundColor(start, false);
+ else
+ */
+ BranchItem *bi = getFramedParentBranch(start);
+ if (bi)
+ return bi->getBranchObj()->getFrameBrushColor();
+
+ // No frame found
+ return model->getMapBackgroundColor();
+}
+
+void BranchItem::setLastSelectedBranch()
+{
+ int d = depth();
+ if (d >= 0) {
+ if (d == 1)
+ // Hack to save an additional lastSelected for mapcenters in
+ // MapEditor depending on orientation this allows to go both left
+ // and right from there
+ if (mo && ((BranchObj *)mo)->getOrientation() ==
+ LinkableMapObj::LeftOfCenter) {
+ ((BranchItem *)parentItem)->lastSelectedBranchNumAlt =
+ parentItem->num(this);
+ return;
+ }
+ ((BranchItem *)parentItem)->lastSelectedBranchNum =
+ parentItem->num(this);
+ }
+}
+
+void BranchItem::setLastSelectedBranch(int i) { lastSelectedBranchNum = i; }
+
+BranchItem *BranchItem::getLastSelectedBranch()
+{
+ if (lastSelectedBranchNum >= branchCounter)
+ return getBranchNum(branchCounter - 1);
+ else
+ return getBranchNum(lastSelectedBranchNum);
+}
+
+BranchItem *BranchItem::getLastSelectedBranchAlt()
+{
+ return getBranchNum(lastSelectedBranchNumAlt);
+}
+
+TreeItem *BranchItem::findMapItem(QPointF p, TreeItem *excludeTI)
+{
+ // Search branches
+ TreeItem *ti;
+ for (int i = 0; i < branchCount(); ++i) {
+ ti = getBranchNum(i)->findMapItem(p, excludeTI);
+ if (ti != NULL)
+ return ti;
+ }
+
+ // Search images
+ ImageItem *ii;
+ for (int i = 0; i < imageCount(); ++i) {
+ ii = getImageNum(i);
+ MapObj *mo = ii->getMO();
+ if (mo && mo->isInClickBox(p) && (ii != excludeTI) &&
+ this != excludeTI && mo->isVisibleObj())
+ return ii;
+ }
+
+ // Search myself
+ if (getBranchObj()->isInClickBox(p) && (this != excludeTI) &&
+ getBranchObj()->isVisibleObj())
+ return this;
+
+ // Search attributes
+ AttributeItem *ai;
+ for (int i = 0; i < attributeCount(); ++i) {
+ ai = getAttributeNum(i);
+ MapObj *mo = ai->getMO();
+ if (mo && mo->isInClickBox(p) && (ai != excludeTI) &&
+ this != excludeTI && mo->isVisibleObj())
+ return ai;
+ }
+ return NULL;
+}
+
+void BranchItem::updateStyles(const bool &keepFrame)
+{
+ // Update styles when relinking branches
+ if (mo) {
+ BranchObj *bo = getBranchObj();
+ if (parentItem != rootItem)
+ bo->setParObj((LinkableMapObj *)(((MapItem *)parentItem)->getMO()));
+ else
+ bo->setParObj(NULL);
+ bo->setDefAttr(BranchObj::MovedBranch, keepFrame);
+ }
+}
+
+BranchObj *BranchItem::getBranchObj() { return (BranchObj *)mo; }
+
+BranchObj *BranchItem::createMapObj(QGraphicsScene *scene)
+{
+ BranchObj *newbo;
+
+ if (parentItem == rootItem) {
+ newbo = new BranchObj(NULL, this);
+ mo = newbo;
+ scene->addItem(newbo);
+ }
+ else {
+ newbo = new BranchObj(((MapItem *)parentItem)->getMO(), this);
+ mo = newbo;
+ // Set visibility depending on parents
+ if (parentItem != rootItem &&
+ (((BranchItem *)parentItem)->scrolled ||
+ !((MapItem *)parentItem)->getLMO()->isVisibleObj()))
+ newbo->setVisibility(false);
+ if (depth() == 1) {
+ qreal r = 190;
+ qreal a =
+ -M_PI_4 + M_PI_2 * (num()) + (M_PI_4 / 2) * (num() / 4 % 4);
+ QPointF p(r * cos(a), r * sin(a));
+ newbo->setRelPos(p);
+ }
+ }
+ newbo->setDefAttr(BranchObj::NewBranch);
+ initLMO();
+
+ if (!getHeading().isEmpty()) {
+ newbo->updateVisuals();
+ newbo->setColor(heading.getColor());
+ }
+
+ return newbo;
+}