1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/branchobj.cpp Thu Jul 17 09:27:20 2008 +0000
1.3 @@ -0,0 +1,1184 @@
1.4 +#include "branchobj.h"
1.5 +#include "texteditor.h"
1.6 +#include "mapeditor.h"
1.7 +#include "mainwindow.h"
1.8 +
1.9 +extern TextEditor *textEditor;
1.10 +extern Main *mainWindow;
1.11 +extern FlagRowObj *standardFlagsDefault;
1.12 +extern QAction *actionEditOpenURL;
1.13 +
1.14 +
1.15 +/////////////////////////////////////////////////////////////////
1.16 +// BranchObj
1.17 +/////////////////////////////////////////////////////////////////
1.18 +
1.19 +BranchObj* BranchObj::itLast=NULL;
1.20 +
1.21 +
1.22 +BranchObj::BranchObj () :OrnamentedObj()
1.23 +{
1.24 +// cout << "Const BranchObj ()\n";
1.25 + setParObj (this);
1.26 + init();
1.27 + depth=-1;
1.28 +}
1.29 +
1.30 +BranchObj::BranchObj (QCanvas* c):OrnamentedObj (c)
1.31 +{
1.32 +// cout << "Const BranchObj (c) called from MapCenterObj (c)\n";
1.33 + canvas=c;
1.34 +}
1.35 +
1.36 +BranchObj::BranchObj (QCanvas* c, LinkableMapObj* p):OrnamentedObj (c)
1.37 +{
1.38 +// cout << "Const BranchObj (c,p)\n";
1.39 + canvas=c;
1.40 + setParObj (p);
1.41 + depth=p->getDepth()+1;
1.42 + if (depth==1)
1.43 + // Calc angle to mapCenter if I am a mainbranch
1.44 + // needed for reordering the mainbranches clockwise
1.45 + // around mapcenter
1.46 + angle=getAngle (QPoint ((int)(x() - parObj->getChildPos().x() ),
1.47 + (int)(y() - parObj->getChildPos().y() ) ) );
1.48 + init();
1.49 +}
1.50 +
1.51 +BranchObj::~BranchObj ()
1.52 +{
1.53 + //cout << "Destr BranchObj\n";
1.54 + // Check, if this branch was the last child to be deleted
1.55 + // If so, unset the scrolled flags
1.56 +
1.57 + BranchObj *po=(BranchObj*)(parObj);
1.58 + if (po)
1.59 + {
1.60 + BranchObj *bo=((BranchObj*)(parObj))->getLastBranch();
1.61 + if (!bo) po->unScroll();
1.62 + }
1.63 +}
1.64 +
1.65 +bool BranchObj::operator< ( const BranchObj & other )
1.66 +{
1.67 + return angle < other.angle;
1.68 +}
1.69 +
1.70 +bool BranchObj::operator== ( const BranchObj & other )
1.71 +{
1.72 + return angle == other.angle;
1.73 +}
1.74 +
1.75 +int BranchObjPtrList::compareItems ( QPtrCollection::Item i, QPtrCollection::Item j)
1.76 +{
1.77 + // Make sure PtrList::find works
1.78 + if (i==j) return 0;
1.79 +
1.80 + if ( ((BranchObj*)(i))->angle > ((BranchObj*)(j))->angle )
1.81 + return 1;
1.82 + else
1.83 + return -1;
1.84 +}
1.85 +
1.86 +void BranchObj::init ()
1.87 +{
1.88 + branch.setAutoDelete (true);
1.89 + floatimage.setAutoDelete (true);
1.90 +
1.91 + absPos=getRandPos();
1.92 + absPos+=parObj->getChildPos();
1.93 +
1.94 + // TODO This should be done in TextObj later
1.95 + QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
1.96 +// font.setPointSize(12);
1.97 + heading->setFont(font );
1.98 +// heading->setText(QObject::tr("new branch"));
1.99 +
1.100 + lastSelectedBranch=-1;
1.101 +
1.102 + setChildObj(this);
1.103 +
1.104 + scrolled=false;
1.105 + tmpUnscrolled=false;
1.106 +
1.107 + url="";
1.108 + vymLink="";
1.109 +}
1.110 +
1.111 +void BranchObj::copy (BranchObj* other)
1.112 +{
1.113 + OrnamentedObj::copy(other);
1.114 +
1.115 + branch.clear();
1.116 + BranchObj* b;
1.117 + for (b=other->branch.first(); b;b=other->branch.next() )
1.118 + // Make deep copy of b
1.119 + // Because addBranch again calls copy for the childs,
1.120 + // Those will get a deep copy, too
1.121 + addBranch(b);
1.122 +
1.123 + FloatImageObj *fi;
1.124 + for (fi=other->floatimage.first(); fi;fi=other->floatimage.next() )
1.125 + addFloatImage (fi);
1.126 +
1.127 + scrolled=other->scrolled;
1.128 + tmpUnscrolled=other->tmpUnscrolled;
1.129 + setVisibility (other->visible);
1.130 +
1.131 + url=other->url;
1.132 + vymLink=other->vymLink;
1.133 +
1.134 + angle=other->angle;
1.135 +
1.136 + positionBBox();
1.137 +}
1.138 +
1.139 +void BranchObj::clear()
1.140 +{
1.141 + branch.clear();
1.142 + floatimage.clear();
1.143 +}
1.144 +
1.145 +int BranchObj::getNum()
1.146 +{
1.147 + if (parObj)
1.148 + return ((BranchObj*)(parObj))->getNum ((BranchObj*)(this));
1.149 + else
1.150 + return 0;
1.151 +}
1.152 +
1.153 +int BranchObj::getNum(BranchObj *bo)
1.154 +{
1.155 + return branch.findRef (bo);
1.156 +}
1.157 +
1.158 +int BranchObj::getFloatImageNum(FloatImageObj *fio)
1.159 +{
1.160 + return floatimage.findRef (fio);
1.161 +}
1.162 +
1.163 +int BranchObj::countBranches()
1.164 +{
1.165 + return branch.count();
1.166 +}
1.167 +
1.168 +int BranchObj::countFloatImages()
1.169 +{
1.170 + return floatimage.count();
1.171 +}
1.172 +
1.173 +void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPoint m, int off)
1.174 +{
1.175 + // Temporary link to lmo
1.176 + // m is position of mouse pointer
1.177 + // offset 0: default 1: below lmo -1 above lmo (if possible)
1.178 +
1.179 +
1.180 + BranchObj* o=(BranchObj*)(lmo);
1.181 + if (!parObjTmpBuf)
1.182 + parObjTmpBuf=parObj;
1.183 +
1.184 + // ignore mapcenter and mainbranch
1.185 + if (lmo->getDepth()<2) off=0;
1.186 + if (off==0)
1.187 + {
1.188 + link2ParPos=false;
1.189 + parObj=o;
1.190 + }
1.191 + else
1.192 + {
1.193 + link2ParPos=true;
1.194 + if (off>0)
1.195 + parObj=o->getParObj();
1.196 + else
1.197 + parObj=o->getParObj();
1.198 + parObj=o;
1.199 + }
1.200 +
1.201 + depth=parObj->getDepth()+1;
1.202 +
1.203 + // setLinkStyle calls updateLink, only set it once
1.204 + if (style!=getDefLinkStyle() ) setLinkStyle (getDefLinkStyle());
1.205 +
1.206 + // Move temporary to new position at destination
1.207 + // Usually the positioning would be done by reposition(),
1.208 + // but then also the destination branch would "Jump" around...
1.209 + // Better just do it approximately
1.210 + if (depth==1)
1.211 + { // new parent is the mapcenter itself
1.212 +
1.213 + QPoint p= normalise ( QPoint (m.x() - o->getChildPos().x(),
1.214 + m.y() - o->getChildPos().y() ));
1.215 + if (p.x()<0) p.setX( p.x()-bbox.width() );
1.216 + move2RelPos (p);
1.217 + } else
1.218 + {
1.219 + int y;
1.220 + if (off==0)
1.221 + {
1.222 + // new parent is just a branch, link to it
1.223 + QRect t=o->getBBoxSizeWithChilds();
1.224 + if (o->getLastBranch())
1.225 + y=t.y() + t.height() ;
1.226 + else
1.227 + y=t.y();
1.228 +
1.229 + } else
1.230 + {
1.231 + if (off<0)
1.232 + // we want to link above lmo
1.233 + y=o->y() - height() + 5;
1.234 + else
1.235 + // we want to link below lmo
1.236 + // Bottom of sel should be 5 pixels above
1.237 + // the bottom of the branch _below_ the target:
1.238 + // Don't try to find that branch, guess 12 pixels
1.239 + y=o->getChildPos().y() -height() + 12;
1.240 + }
1.241 + if (o->getOrientation()==OrientLeftOfCenter)
1.242 + move ( o->getChildPos().x() - linkwidth, y );
1.243 + else
1.244 + move (o->getChildPos().x() + linkwidth, y );
1.245 + }
1.246 +
1.247 + // updateLink is called implicitly in move
1.248 + reposition(); // FIXME shouldn't be this a request?
1.249 +}
1.250 +
1.251 +void BranchObj::unsetParObjTmp()
1.252 +{
1.253 + if (parObjTmpBuf)
1.254 + {
1.255 + link2ParPos=false;
1.256 + parObj=parObjTmpBuf;
1.257 + parObjTmpBuf=NULL;
1.258 + depth=parObj->getDepth()+1;
1.259 + setLinkStyle (getDefLinkStyle() );
1.260 + }
1.261 +}
1.262 +
1.263 +void BranchObj::unScroll()
1.264 +{
1.265 + if (tmpUnscrolled) resetTmpUnscroll();
1.266 + if (scrolled) toggleScroll();
1.267 +}
1.268 +
1.269 +void BranchObj::toggleScroll()
1.270 +{
1.271 + BranchObj *bo;
1.272 + if (scrolled)
1.273 + {
1.274 + scrolled=false;
1.275 + systemFlags->deactivate("scrolledright");
1.276 + for (bo=branch.first(); bo; bo=branch.next() )
1.277 + {
1.278 + bo->setVisibility(true);
1.279 + }
1.280 + } else
1.281 + {
1.282 + scrolled=true;
1.283 + systemFlags->activate("scrolledright");
1.284 + for (bo=branch.first(); bo; bo=branch.next() )
1.285 + {
1.286 + bo->setVisibility(false);
1.287 + }
1.288 + }
1.289 + calcBBoxSize();
1.290 + positionBBox();
1.291 + move (absPos.x(), absPos.y() );
1.292 + forceReposition();
1.293 +}
1.294 +
1.295 +bool BranchObj::isScrolled()
1.296 +{
1.297 + return scrolled;
1.298 +}
1.299 +
1.300 +bool BranchObj::hasScrolledParent(BranchObj *start)
1.301 +{
1.302 + // Calls parents recursivly to
1.303 + // find out, if we are scrolled at all.
1.304 + // But ignore myself, just look at parents.
1.305 +
1.306 + if (this !=start && scrolled) return true;
1.307 +
1.308 + BranchObj* bo=(BranchObj*)(parObj);
1.309 + if (bo)
1.310 + return bo->hasScrolledParent(start);
1.311 + else
1.312 + return false;
1.313 +}
1.314 +
1.315 +void BranchObj::tmpUnscroll()
1.316 +{
1.317 + // Unscroll parent (recursivly)
1.318 + BranchObj* bo=(BranchObj*)(parObj);
1.319 + if (bo) bo->tmpUnscroll();
1.320 +
1.321 + // Unscroll myself
1.322 + if (scrolled)
1.323 + {
1.324 + tmpUnscrolled=true;
1.325 + systemFlags->activate("tmpUnscrolledright");
1.326 + toggleScroll();
1.327 + }
1.328 +}
1.329 +
1.330 +void BranchObj::resetTmpUnscroll()
1.331 +{
1.332 + // Unscroll parent (recursivly)
1.333 + BranchObj* bo=(BranchObj*)(parObj);
1.334 + if (bo)
1.335 + bo->resetTmpUnscroll();
1.336 +
1.337 + // Unscroll myself
1.338 + if (tmpUnscrolled)
1.339 + {
1.340 + tmpUnscrolled=false;
1.341 + systemFlags->deactivate("tmpUnscrolledright");
1.342 + toggleScroll();
1.343 + }
1.344 +}
1.345 +
1.346 +void BranchObj::setVisibility(bool v, int toDepth)
1.347 +{
1.348 + if (depth <= toDepth)
1.349 + {
1.350 + frame->setVisibility(v);
1.351 + heading->setVisibility(v);
1.352 + systemFlags->setVisibility(v);
1.353 + standardFlags->setVisibility(v);
1.354 + LinkableMapObj::setVisibility (v);
1.355 +
1.356 + if (!scrolled && (depth < toDepth))
1.357 + {
1.358 + // Now go recursivly through all childs
1.359 + BranchObj* b;
1.360 + for (b=branch.first(); b;b=branch.next() )
1.361 + b->setVisibility (v,toDepth);
1.362 + FloatImageObj *fio;
1.363 + for (fio=floatimage.first(); fio; fio=floatimage.next())
1.364 + fio->setVisibility (v);
1.365 + }
1.366 + } // depth <= toDepth
1.367 + move (absPos.x(), absPos.y() );
1.368 + requestReposition();
1.369 +}
1.370 +
1.371 +void BranchObj::setVisibility(bool v)
1.372 +{
1.373 + setVisibility (v,MAX_DEPTH);
1.374 +}
1.375 +
1.376 +
1.377 +void BranchObj::setLinkColor ()
1.378 +{
1.379 + // Overloaded from LinkableMapObj
1.380 + // BranchObj can use color of heading
1.381 +
1.382 + if (mapEditor->getLinkColorHint()==HeadingColor)
1.383 + LinkableMapObj::setLinkColor (heading->getColor() );
1.384 + else
1.385 + LinkableMapObj::setLinkColor ();
1.386 +}
1.387 +
1.388 +void BranchObj::setColor (QColor col, bool colorChilds)
1.389 +{
1.390 + heading->setColor(col);
1.391 + setLinkColor();
1.392 + if (colorChilds)
1.393 + {
1.394 + BranchObj *bo;
1.395 + for (bo=branch.first(); bo; bo=branch.next() )
1.396 + bo->setColor(col,colorChilds);
1.397 + }
1.398 +}
1.399 +
1.400 +
1.401 +BranchObj* BranchObj::first()
1.402 +{
1.403 + itLast=NULL;
1.404 + return this;
1.405 +}
1.406 +
1.407 +BranchObj* BranchObj::next()
1.408 +{
1.409 + BranchObj *lmo;
1.410 + BranchObj *bo=branch.first();
1.411 + BranchObj *po=(BranchObj*)(parObj);
1.412 +
1.413 + if (!itLast)
1.414 + { // We are just beginning at the mapCenter
1.415 + if (bo)
1.416 + {
1.417 + itLast=this;
1.418 + return bo;
1.419 + }
1.420 + else
1.421 + {
1.422 + itLast=NULL;
1.423 + return NULL;
1.424 + }
1.425 + }
1.426 +
1.427 + if (itLast==parObj)
1.428 + { // We come from above
1.429 + if (bo)
1.430 + {
1.431 + // there are childs, go there
1.432 + itLast=this;
1.433 + return bo;
1.434 + }
1.435 + else
1.436 + { // no childs, try to go up again
1.437 + if (po)
1.438 + {
1.439 + // go up
1.440 + itLast=this;
1.441 + lmo=po->next();
1.442 + itLast=this;
1.443 + return lmo;
1.444 +
1.445 + }
1.446 + else
1.447 + {
1.448 + // can't go up, I am mapCenter
1.449 + itLast=NULL;
1.450 + return NULL;
1.451 + }
1.452 + }
1.453 + }
1.454 +
1.455 + // Try to find last child, we came from, in my own childs
1.456 + bool searching=true;
1.457 + while (bo && searching)
1.458 + {
1.459 + if (itLast==bo) searching=false;
1.460 + bo=branch.next();
1.461 + }
1.462 + if (!searching)
1.463 + { // found lastLMO in my childs
1.464 + if (bo)
1.465 + {
1.466 + // found a brother of lastLMO
1.467 + itLast=this;
1.468 + return bo;
1.469 + }
1.470 + else
1.471 + {
1.472 + if (po)
1.473 + {
1.474 + // go up
1.475 + itLast=this;
1.476 + lmo=po->next();
1.477 + itLast=this;
1.478 + return lmo;
1.479 + }
1.480 + else
1.481 + {
1.482 + // can't go up, I am mapCenter
1.483 + itLast=NULL;
1.484 + return NULL;
1.485 + }
1.486 + }
1.487 + }
1.488 +
1.489 + // couldn't find last child, it must be a nephew of mine
1.490 + bo=branch.first();
1.491 + if (bo)
1.492 + {
1.493 + // proceed with my first child
1.494 + itLast=this;
1.495 + return bo;
1.496 + }
1.497 + else
1.498 + {
1.499 + // or go back to my parents
1.500 + if (po)
1.501 + {
1.502 + // go up
1.503 + itLast=this;
1.504 + lmo=po->next();
1.505 + itLast=this;
1.506 + return lmo;
1.507 + }
1.508 + else
1.509 + {
1.510 + // can't go up, I am mapCenter
1.511 + itLast=NULL;
1.512 + return NULL;
1.513 + }
1.514 + }
1.515 +}
1.516 +
1.517 +BranchObj* BranchObj::getLastIterator()
1.518 +{
1.519 + return itLast;
1.520 +}
1.521 +
1.522 +void BranchObj::setLastIterator(BranchObj* it)
1.523 +{
1.524 + itLast=it;
1.525 +}
1.526 +
1.527 +
1.528 +void BranchObj::move (double x, double y)
1.529 +{
1.530 + OrnamentedObj::move (x,y);
1.531 + positionBBox();
1.532 +}
1.533 +
1.534 +void BranchObj::move (QPoint p)
1.535 +{
1.536 + move (p.x(), p.y());
1.537 +}
1.538 +
1.539 +void BranchObj::moveBy (double x, double y)
1.540 +{
1.541 + OrnamentedObj::moveBy (x,y);
1.542 + positionBBox();
1.543 + BranchObj* b;
1.544 + for (b=branch.first(); b;b=branch.next() )
1.545 + b->moveBy (x,y);
1.546 +}
1.547 +
1.548 +void BranchObj::moveBy (QPoint p)
1.549 +{
1.550 + moveBy (p.x(), p.y());
1.551 +}
1.552 +
1.553 +
1.554 +void BranchObj::positionBBox()
1.555 +{
1.556 +
1.557 + heading->positionBBox();
1.558 + systemFlags->positionBBox();
1.559 + standardFlags->positionBBox();
1.560 + // It seems that setting x,y also affects width,height
1.561 + int w_old=bbox.width();
1.562 + int h_old=bbox.height();
1.563 + bbox.setX (absPos.x() );
1.564 + bbox.setY (absPos.y() );
1.565 + bbox.setWidth(w_old);
1.566 + bbox.setHeight(h_old);
1.567 +
1.568 +
1.569 + setSelBox();
1.570 +
1.571 + // set the frame
1.572 + frame->setRect(QRect(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
1.573 +}
1.574 +
1.575 +void BranchObj::calcBBoxSize()
1.576 +{
1.577 + QSize heading_r=heading->getSize();
1.578 + int heading_w=static_cast <int> (heading_r.width() );
1.579 + int heading_h=static_cast <int> (heading_r.height() );
1.580 + QSize sysflags_r=systemFlags->getSize();
1.581 + int sysflags_h=sysflags_r.height();
1.582 + int sysflags_w=sysflags_r.width();
1.583 + QSize stanflags_r=standardFlags->getSize();
1.584 + int stanflags_h=stanflags_r.height();
1.585 + int stanflags_w=stanflags_r.width();
1.586 + int w;
1.587 + int h;
1.588 +
1.589 + // set width to sum of all widths
1.590 + w=heading_w + sysflags_w + stanflags_w;
1.591 + // set height to maximum needed height
1.592 + h=max (sysflags_h,stanflags_h);
1.593 + h=max (h,heading_h);
1.594 +
1.595 + w+=frame->getBorder();
1.596 + h+=frame->getBorder();
1.597 + bbox.setSize (QSize (w,h));
1.598 +}
1.599 +
1.600 +LinkableMapObj* BranchObj::findMapObj(QPoint p, LinkableMapObj* excludeLMO)
1.601 +{
1.602 + // Search branches
1.603 + BranchObj *b;
1.604 + LinkableMapObj *lmo;
1.605 + for (b=branch.first(); b; b=branch.next() )
1.606 + {
1.607 + lmo=b->findMapObj(p, excludeLMO);
1.608 + if (lmo != NULL) return lmo;
1.609 + }
1.610 +
1.611 + // Search myself
1.612 + if (inBBox (p) && (this != excludeLMO) && isVisibleObj() )
1.613 + return this;
1.614 +
1.615 + // Search float images
1.616 + FloatImageObj *foi;
1.617 + for (foi=floatimage.first(); foi; foi=floatimage.next() )
1.618 + if (foi->inBBox(p) && (foi != excludeLMO) && foi->getParObj()!= excludeLMO) return foi;
1.619 +
1.620 + return NULL;
1.621 +}
1.622 +
1.623 +void BranchObj::setHeading(QString s)
1.624 +{
1.625 + // Adjusting font size
1.626 + QFont font=heading->getFont();
1.627 + if (depth==0)
1.628 + font.setPointSize(16);
1.629 + else
1.630 + if (depth>1)
1.631 + font.setPointSize(10);
1.632 + else
1.633 + font.setPointSize(12);
1.634 + heading->setFont(font);
1.635 + heading->setText(s); // set new heading
1.636 + calcBBoxSize(); // recalculate bbox
1.637 + positionBBox(); // rearrange contents
1.638 + requestReposition();
1.639 +}
1.640 +
1.641 +void BranchObj::setURL(QString s)
1.642 +{
1.643 + url=s;
1.644 + if (!url.isEmpty())
1.645 + systemFlags->activate("url");
1.646 + else
1.647 + systemFlags->deactivate("url");
1.648 + calcBBoxSize(); // recalculate bbox
1.649 + positionBBox(); // rearrange contents
1.650 + forceReposition();
1.651 +}
1.652 +
1.653 +QString BranchObj::getURL()
1.654 +{
1.655 + return url;
1.656 +}
1.657 +
1.658 +void BranchObj::setVymLink(QString s)
1.659 +{
1.660 + if (!s.isEmpty())
1.661 + {
1.662 + // We need the relative (from loading)
1.663 + // or absolute path (from User event)
1.664 + // and build the absolute path.
1.665 + // Note: If we have relative, use path of
1.666 + // current map to build absolute path
1.667 + QDir d(s);
1.668 + if (!d.path().startsWith ("/"))
1.669 + {
1.670 + QString p=mapEditor->getDestPath();
1.671 + int i=p.findRev("/",-1);
1.672 + d.setPath(p.left(i)+"/"+s);
1.673 + d.convertToAbs();
1.674 + }
1.675 + vymLink=d.path();
1.676 + systemFlags->activate("vymLink");
1.677 + }
1.678 + else
1.679 + {
1.680 + systemFlags->deactivate("vymLink");
1.681 + vymLink="";
1.682 + }
1.683 + calcBBoxSize(); // recalculate bbox
1.684 + positionBBox(); // rearrange contents
1.685 + forceReposition();
1.686 +}
1.687 +
1.688 +QString BranchObj::getVymLink()
1.689 +{
1.690 + return vymLink;
1.691 +}
1.692 +
1.693 +QString BranchObj::saveToDir (const QString &tmpdir,const QString &prefix, const QPoint& offset)
1.694 +{
1.695 + QString s,a;
1.696 + QString scrolledAttr;
1.697 + if (scrolled)
1.698 + scrolledAttr=attribut ("scrolled","yes");
1.699 + else
1.700 + scrolledAttr="";
1.701 +
1.702 + QString posAttr;
1.703 + if (depth<2) posAttr=
1.704 + attribut("absPosX",QString().setNum(absPos.x(),10)) +
1.705 + attribut("absPosY",QString().setNum(absPos.y(),10));
1.706 + else
1.707 + posAttr="";
1.708 +
1.709 + QString urlAttr;
1.710 + if (!url.isEmpty())
1.711 + urlAttr=attribut ("url",url);
1.712 +
1.713 + QString vymLinkAttr;
1.714 + if (!vymLink.isEmpty())
1.715 + vymLinkAttr=attribut ("vymLink",convertToRel(mapEditor->getDestPath(),vymLink) );
1.716 +
1.717 + QString frameAttr;
1.718 + if (frame->getFrameType()!=NoFrame)
1.719 + frameAttr=attribut ("frameType",frame->getFrameTypeName());
1.720 + else
1.721 + frameAttr="";
1.722 +
1.723 + // save area, if not scrolled
1.724 + QString areaAttr;
1.725 + if (!((BranchObj*)(parObj))->isScrolled() )
1.726 + {
1.727 + areaAttr=
1.728 + attribut("x1",QString().setNum(absPos.x()-offset.x(),10)) +
1.729 + attribut("y1",QString().setNum(absPos.y()-offset.y(),10)) +
1.730 + attribut("x2",QString().setNum(absPos.x()+width()-offset.x(),10)) +
1.731 + attribut("y2",QString().setNum(absPos.y()+height()-offset.y(),10));
1.732 +
1.733 + } else
1.734 + areaAttr="";
1.735 +
1.736 + s=beginElement ("branch" +scrolledAttr +posAttr +urlAttr +vymLinkAttr +frameAttr +areaAttr);
1.737 + incIndent();
1.738 +
1.739 + // save heading
1.740 + s=s+valueElement("heading", getHeading(),
1.741 + attribut ("textColor",QColor(heading->getColor()).name()));
1.742 +
1.743 + // save names of flags set
1.744 + s+=standardFlags->saveToDir(tmpdir,prefix,0);
1.745 +
1.746 + // save note
1.747 + if (!note.isEmpty() )
1.748 + s+=note.saveToDir();
1.749 +
1.750 + // Save branches
1.751 + BranchObj *bo;
1.752 + for (bo=branch.first(); bo; bo=branch.next() )
1.753 + s+=bo->saveToDir(tmpdir,prefix,offset);
1.754 + decIndent();
1.755 +
1.756 + // Save FloatImages
1.757 + FloatImageObj *fio;
1.758 + for (fio=floatimage.first(); fio; fio=floatimage.next() )
1.759 + s+=fio->saveToDir (tmpdir,prefix);
1.760 +
1.761 + s+=endElement ("branch");
1.762 + return s;
1.763 +}
1.764 +
1.765 +LinkableMapObj* BranchObj::addFloatImage ()
1.766 +{
1.767 + FloatImageObj *newfi=new FloatImageObj (canvas,this);
1.768 + floatimage.append (newfi);
1.769 + if (hasScrolledParent(this) )
1.770 + newfi->setVisibility (false);
1.771 + else
1.772 + newfi->setVisibility(visible);
1.773 + requestReposition();
1.774 + return newfi;
1.775 +}
1.776 +
1.777 +LinkableMapObj* BranchObj::addFloatImage (FloatImageObj *fio)
1.778 +{
1.779 + FloatImageObj *newfi=new FloatImageObj (canvas,this);
1.780 + floatimage.append (newfi);
1.781 + newfi->copy (fio);
1.782 + if (hasScrolledParent(this) )
1.783 + newfi->setVisibility (false);
1.784 + else
1.785 + newfi->setVisibility(visible);
1.786 + requestReposition();
1.787 + return newfi;
1.788 +}
1.789 +
1.790 +FloatImageObj* BranchObj::getFirstFloatImage ()
1.791 +{
1.792 + return floatimage.first();
1.793 +}
1.794 +
1.795 +FloatImageObj* BranchObj::getLastFloatImage ()
1.796 +{
1.797 + return floatimage.last();
1.798 +}
1.799 +
1.800 +FloatImageObj* BranchObj::getFloatImageNum (const uint &i)
1.801 +{
1.802 + return floatimage.at(i);
1.803 +}
1.804 +
1.805 +void BranchObj::removeFloatImage (FloatImageObj *fio)
1.806 +{
1.807 + floatimage.remove (fio);
1.808 + requestReposition();
1.809 +}
1.810 +
1.811 +void BranchObj::savePosInAngle ()
1.812 +{
1.813 + // Save position in angle
1.814 + BranchObj *b;
1.815 + int i=0;
1.816 + for (b=branch.first(); b; b=branch.next() )
1.817 + {
1.818 + b->angle=i;
1.819 + i++;
1.820 + }
1.821 +}
1.822 +
1.823 +BranchObj* BranchObj::addBranch()
1.824 +{
1.825 + BranchObj* newbo=new BranchObj(canvas,this);
1.826 + branch.append (newbo);
1.827 + newbo->setParObj(this);
1.828 + newbo->setColor(getColor(),false);
1.829 + newbo->setLinkColor();
1.830 + newbo->setHeading ("new");
1.831 + newbo->setLinkStyle (newbo->getDefLinkStyle());
1.832 + if (scrolled)
1.833 + newbo->setVisibility (false);
1.834 + else
1.835 + newbo->setVisibility(visible);
1.836 + requestReposition();
1.837 + return newbo;
1.838 +}
1.839 +
1.840 +BranchObj* BranchObj::addBranch(BranchObj* bo)
1.841 +{
1.842 + BranchObj* newbo=new BranchObj(canvas,this);
1.843 + branch.append (newbo);
1.844 + newbo->copy(bo);
1.845 + newbo->setParObj(this);
1.846 + newbo->setHeading (newbo->getHeading()); // adjust fontsize to depth
1.847 + newbo->setLinkStyle (newbo->getDefLinkStyle());
1.848 + if (scrolled)
1.849 + newbo->setVisibility (false);
1.850 + else
1.851 + newbo->setVisibility(bo->visible);
1.852 + requestReposition();
1.853 + return newbo;
1.854 +}
1.855 +
1.856 +BranchObj* BranchObj::insertBranch(int pos)
1.857 +{
1.858 + savePosInAngle();
1.859 + // Add new bo and resort branches
1.860 + BranchObj *newbo=addBranch ();
1.861 + newbo->angle=pos-0.5;
1.862 + branch.sort();
1.863 + return newbo;
1.864 +}
1.865 +
1.866 +BranchObj* BranchObj::insertBranch(BranchObj* bo, int pos)
1.867 +{
1.868 + savePosInAngle();
1.869 + // Add new bo and resort branches
1.870 + bo->angle=pos-0.5;
1.871 + BranchObj *newbo=addBranch (bo);
1.872 + branch.sort();
1.873 + return newbo;
1.874 +}
1.875 +
1.876 +void BranchObj::removeBranch(BranchObj* bo)
1.877 +{
1.878 + // if bo is not in branch remove returns false, we
1.879 + // don't care...
1.880 + branch.remove (bo);
1.881 + requestReposition();
1.882 +}
1.883 +
1.884 +void BranchObj::setLastSelectedBranch (BranchObj* bo)
1.885 +{
1.886 + lastSelectedBranch=branch.find(bo);
1.887 +}
1.888 +
1.889 +BranchObj* BranchObj::getLastSelectedBranch ()
1.890 +{
1.891 + if (lastSelectedBranch>=0)
1.892 + {
1.893 + BranchObj* bo=branch.at(lastSelectedBranch);
1.894 + if (bo) return bo;
1.895 + }
1.896 + return branch.first();
1.897 +}
1.898 +
1.899 +BranchObj* BranchObj::getFirstBranch ()
1.900 +{
1.901 + return branch.first();
1.902 +}
1.903 +
1.904 +BranchObj* BranchObj::getLastBranch ()
1.905 +{
1.906 + return branch.last();
1.907 +}
1.908 +
1.909 +BranchObj* BranchObj::getBranchNum (const uint &i)
1.910 +{
1.911 + return branch.at(i);
1.912 +}
1.913 +
1.914 +
1.915 +BranchObj* BranchObj::moveBranchUp(BranchObj* bo1) // move a branch up (modify myself)
1.916 +{
1.917 + savePosInAngle();
1.918 + int i=branch.find(bo1);
1.919 + if (i>0)
1.920 + { // -1 if bo1 not found
1.921 + branch.at(i)->angle--;
1.922 + branch.at(i-1)->angle++;
1.923 + branch.sort();
1.924 + return branch.at(i-1);
1.925 + } else
1.926 + return branch.at(i);
1.927 +}
1.928 +
1.929 +BranchObj* BranchObj::moveBranchDown(BranchObj* bo1)
1.930 +{
1.931 + savePosInAngle();
1.932 + int i=branch.find(bo1);
1.933 + int j;
1.934 + if (branch.next())
1.935 + {
1.936 + j = branch.at();
1.937 + branch.at(i)->angle++;
1.938 + branch.at(j)->angle--;
1.939 + branch.sort();
1.940 + return branch.at(j);
1.941 + } else
1.942 + return branch.at(i);
1.943 +}
1.944 +
1.945 +void BranchObj::alignRelativeTo (QPoint ref)
1.946 +{
1.947 +/* FIXME testing
1.948 + if (!getHeading().isEmpty())
1.949 + cout << "BO::alignRelTo "<<getHeading()<<endl;
1.950 + else
1.951 + cout << "BO::alignRelTo ???"<<endl;
1.952 + cout << " d="<<depth<<endl;
1.953 +*/
1.954 + int th = bboxTotal.height();
1.955 +
1.956 + // If I am the mapcenter or a mainbranch, reposition heading
1.957 + if (depth<2)
1.958 + {
1.959 + move (absPos.x(),absPos.y());
1.960 + if (depth==1)
1.961 + {
1.962 + // Calc angle to mapCenter if I am a mainbranch
1.963 + // needed for reordering the mainbranches clockwise
1.964 + // around mapcenter
1.965 + angle=getAngle (QPoint ((int)(x() - parObj->getChildPos().x() ),
1.966 + (int)(y() - parObj->getChildPos().y() ) ) );
1.967 + }
1.968 + }
1.969 + else
1.970 + {
1.971 + // Align myself depending on orientation and parent, but
1.972 + // only if I am not the mainbranch or mapcenter itself
1.973 + switch (orientation)
1.974 + {
1.975 + case OrientLeftOfCenter:
1.976 + move (ref.x()-bbox.width(), ref.y() + (th-bbox.height())/2 );
1.977 + break;
1.978 + case OrientRightOfCenter:
1.979 + move (ref.x(), ref.y() + (th-bbox.height())/2 );
1.980 + break;
1.981 + default:
1.982 + cout <<"LMO::alignRelativeTo: oops, no orientation given...\n";
1.983 + break;
1.984 + }
1.985 + }
1.986 +
1.987 + FloatImageObj *fio;
1.988 + for (fio=floatimage.first(); fio; fio=floatimage.next() )
1.989 + fio->reposition();
1.990 +
1.991 + if (scrolled) return;
1.992 +
1.993 + // Set reference point for alignment of childs
1.994 + QPoint ref2;
1.995 + if (orientation==OrientLeftOfCenter)
1.996 + ref2.setX(childPos.x() - linkwidth);
1.997 + else
1.998 + ref2.setX(childPos.x() + linkwidth);
1.999 +
1.1000 + if (depth==1)
1.1001 + ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
1.1002 + else
1.1003 + ref2.setY(ref.y() );
1.1004 +
1.1005 + // Align the childs depending on reference point
1.1006 + BranchObj *b;
1.1007 + for (b=branch.first(); b; b=branch.next() )
1.1008 + {
1.1009 + b->alignRelativeTo (ref2);
1.1010 + ref2.setY(ref2.y() + b->getBBoxSizeWithChilds().height() );
1.1011 + }
1.1012 +}
1.1013 +
1.1014 +
1.1015 +void BranchObj::reposition()
1.1016 +{
1.1017 +/* FIXME testing
1.1018 + if (!getHeading().isEmpty())
1.1019 + cout << "BO::reposition "<<getHeading()<<endl;
1.1020 + else
1.1021 + cout << "BO::reposition ???"<<endl;
1.1022 +*/
1.1023 + if (depth==0)
1.1024 + {
1.1025 + // only calculate the sizes once. If the deepest LMO
1.1026 + // changes its height,
1.1027 + // all upper LMOs have to change, too.
1.1028 + calcBBoxSizeWithChilds();
1.1029 + alignRelativeTo ( QPoint (absPos.x(),
1.1030 + absPos.y()-(bboxTotal.height()-bbox.height())/2) );
1.1031 + branch.sort();
1.1032 + } else
1.1033 + {
1.1034 + // This is only important for moving branches:
1.1035 + // For editing a branch it isn't called...
1.1036 + alignRelativeTo ( QPoint (absPos.x(),
1.1037 + absPos.y()-(bboxTotal.height()-bbox.height())/2) );
1.1038 + }
1.1039 +}
1.1040 +
1.1041 +
1.1042 +QRect BranchObj::getTotalBBox()
1.1043 +{
1.1044 + QRect r=bbox;
1.1045 +
1.1046 + if (scrolled) return r;
1.1047 +
1.1048 + BranchObj* b;
1.1049 + for (b=branch.first();b ;b=branch.next() )
1.1050 + r=addBBox(b->getTotalBBox(),r);
1.1051 +
1.1052 + FloatImageObj* fio;
1.1053 + for (fio=floatimage.first();fio ;fio=floatimage.next() )
1.1054 + r=addBBox(fio->getTotalBBox(),r);
1.1055 +
1.1056 + return r;
1.1057 +}
1.1058 +
1.1059 +QRect BranchObj::getBBoxSizeWithChilds()
1.1060 +{
1.1061 + return bboxTotal;
1.1062 +}
1.1063 +
1.1064 +void BranchObj::calcBBoxSizeWithChilds()
1.1065 +{
1.1066 + // This is called only from reposition and
1.1067 + // and only for mapcenter. So it won't be
1.1068 + // called more than once for a single user
1.1069 + // action
1.1070 +
1.1071 + // Calculate size of LMO including all childs (to align them later)
1.1072 +
1.1073 + bboxTotal.setX(bbox.x() );
1.1074 + bboxTotal.setY(bbox.y() );
1.1075 +
1.1076 + // if branch is scrolled, ignore childs, but still consider floatimages
1.1077 + if (scrolled)
1.1078 + {
1.1079 + bboxTotal.setWidth (bbox.width());
1.1080 + bboxTotal.setHeight(bbox.height());
1.1081 + return;
1.1082 + }
1.1083 +
1.1084 + QRect r(0,0,0,0);
1.1085 + QRect br;
1.1086 + // Now calculate recursivly
1.1087 + // sum of heights
1.1088 + // maximum of widths
1.1089 + // minimum of y
1.1090 + BranchObj* b;
1.1091 + for (b=branch.first();b ;b=branch.next() )
1.1092 + {
1.1093 + b->calcBBoxSizeWithChilds();
1.1094 + br=b->getBBoxSizeWithChilds();
1.1095 + r.setWidth( max (br.width(), r.width() ));
1.1096 + r.setHeight(br.height() + r.height() );
1.1097 + if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
1.1098 + }
1.1099 + // Add myself and also
1.1100 + // add width of link to sum if necessary
1.1101 + if (branch.isEmpty())
1.1102 + bboxTotal.setWidth (bbox.width() + r.width() );
1.1103 + else
1.1104 + bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
1.1105 + bboxTotal.setHeight(max (r.height(), bbox.height() ) );
1.1106 +// frame->setRect(QRect(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
1.1107 +}
1.1108 +
1.1109 +void BranchObj::select()
1.1110 +{
1.1111 + LinkableMapObj::select();
1.1112 + // Tell parent that I am selected now:
1.1113 + BranchObj* po=(BranchObj*)(parObj);
1.1114 + if (po) // TODO Try to get rid of this cast...
1.1115 + po->setLastSelectedBranch(this);
1.1116 +
1.1117 + // temporary unscroll, if we have scrolled parents somewhere
1.1118 + if (parObj) ((BranchObj*)(parObj))->tmpUnscroll();
1.1119 +
1.1120 + // set Text in Editor
1.1121 + textEditor->setText(note.getNote() );
1.1122 + textEditor->setFilename(note.getFilenameHint() );
1.1123 + textEditor->setFontHint (note.getFontHint() );
1.1124 + connect (textEditor, SIGNAL (textHasChanged() ), this, SLOT (updateNoteFlag() ) );
1.1125 + connect (textEditor, SIGNAL (fontSizeHasChanged() ), this, SLOT (updateNoteFlag() ) );
1.1126 +
1.1127 + // Show URL and link in statusbar
1.1128 + QString status;
1.1129 + if (!url.isEmpty()) status+="URL: "+url+" ";
1.1130 + if (!vymLink.isEmpty()) status+="Link: "+vymLink;
1.1131 + if (!status.isEmpty()) mainWindow->statusMessage (status);
1.1132 +
1.1133 + // Update Toolbar
1.1134 + standardFlags->updateToolBar();
1.1135 +
1.1136 + // Update Browserbutton
1.1137 + if (!url.isEmpty())
1.1138 + actionEditOpenURL->setEnabled (true);
1.1139 + else
1.1140 + actionEditOpenURL->setEnabled (false);
1.1141 +
1.1142 + // Update actions in mapeditor
1.1143 + mapEditor->updateActions();
1.1144 +}
1.1145 +
1.1146 +void BranchObj::unselect()
1.1147 +{
1.1148 + LinkableMapObj::unselect();
1.1149 + // Delete any messages like vymLink in StatusBar
1.1150 + mainWindow->statusMessage ("");
1.1151 +
1.1152 + // save note from editor and set flag
1.1153 + // text is done by updateNoteFlag(), just save
1.1154 + // filename here
1.1155 + note.setFilenameHint (textEditor->getFilename());
1.1156 +
1.1157 + // reset temporary unscroll, if we have scrolled parents somewhere
1.1158 + if (parObj) ((BranchObj*)(parObj))->resetTmpUnscroll();
1.1159 +
1.1160 + // Disconnect textEditor from this LMO
1.1161 + disconnect( textEditor, SIGNAL(textHasChanged()), 0, 0 );
1.1162 + disconnect( textEditor, SIGNAL (fontSizeHasChanged()),0,0 );
1.1163 +
1.1164 + // Erase content of editor
1.1165 + textEditor->setInactive();
1.1166 +
1.1167 + // unselect all buttons in toolbar
1.1168 + standardFlagsDefault->updateToolBar();
1.1169 +}
1.1170 +
1.1171 +QString BranchObj::getSelectString()
1.1172 +{
1.1173 + QString s;
1.1174 + if (parObj)
1.1175 + {
1.1176 + if (parObj->getDepth()==0)
1.1177 + s= "bo:" + QString("%1").arg(getNum());
1.1178 + else
1.1179 + s= ((BranchObj*)(parObj))->getSelectString() + ",bo:" + QString("%1").arg(getNum());
1.1180 + } else
1.1181 + {
1.1182 + s="mc:";
1.1183 + }
1.1184 +
1.1185 + return s;
1.1186 +}
1.1187 +