#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(const QList<QVariant> &data, TreeItem *parent):MapItem (data,parent)
{
//qDebug()<< "Constr. BranchItem this="<<this;
// 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 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.saveToDir(tmpdir,prefix,0);
// 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 note
if (!note.isEmpty() )
s+=note.saveToDir();
// 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::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("system-scrolledright");
if (branchCounter>0)
for (int i=0;i<branchCounter;++i)
{
bo=(BranchObj*)(getBranchNum(i)->getMO());
if (bo) bo->setVisibility(true);
}
} else
{
scrolled=true;
systemFlags.activate("system-scrolledright");
if (branchCounter>0)
for (int i=0;i<branchCounter;++i)
{
bo=(BranchObj*)(getBranchNum(i)->getMO());
if (bo) bo->setVisibility(false);
}
}
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("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("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;
}
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->updateData();
newbo->setColor (heading.getColor());
}
return newbo;
}