# HG changeset patch # User insilmaril # Date 1216293115 0 # Node ID 394b2f297e1d6f8c141ebba597750914f0c6fb55 # Parent e37153bea487db698000c8f5a0f880401681131d Deleting an animated part no longer segfaults diff -r e37153bea487 -r 394b2f297e1d INSTALL.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/INSTALL.txt Thu Jul 17 11:11:55 2008 +0000 @@ -0,0 +1,59 @@ +Installation of vym - view your mind +==================================== + +Contents +-------- + +A) openSUSE 10.2 +B) openSUSE 10.3 and 11.0 +C) Mac OS X 10.3+ + +More systems like Debian are likely to be added later. Please +send feedback about installation on your Operating System to +vym@InSilmaril.de + +For general questions please contact the vym mailinglist: + + vym-forum@lists.sourceforge.net + + +A) openSUSE 10.2 +================ + +vym needs a newer version of Trolltechs Qt libraries than the one on the +10.2 installation media. This new version can be installed easily in +YaST: + + - Select "Installation Source" + - Add a HTTP source: + Server: repos.opensuse.org + Directory: /KDE:/Qt/openSUSE_10.2/ + Authentication: Anonymous + + - Select "Software Management" + - Search for "libqt4" + - Install all found packages. (They have a version >= 4.3.0-55.1) + +B) openSUSE 10.2 and later +========================== + +Get the rpms e.g. from here: + +http://download.opensuse.org/repositories/home://insilmaril/ + +and install the (as root): + +yast -i vym-[VERSION].rpm + +C) Mac OS X 10.3+ +================= + +After opening the disk image vym-1.9.0.dmg you can copy vym.app to +/Applications. This will need administrator rights. + + +This release of vym includes the Qt libraries. For more information on +Qt see http://www.trolltech.com. + + + diff -r e37153bea487 -r 394b2f297e1d branchobj.cpp --- a/branchobj.cpp Thu Jul 17 09:27:20 2008 +0000 +++ b/branchobj.cpp Thu Jul 17 11:11:55 2008 +0000 @@ -1,12 +1,16 @@ #include "branchobj.h" -#include "texteditor.h" + +// #include "texteditor.h" +#include "geometry.h" #include "mapeditor.h" #include "mainwindow.h" +#include "misc.h" + +class TextEditor; extern TextEditor *textEditor; extern Main *mainWindow; extern FlagRowObj *standardFlagsDefault; -extern QAction *actionEditOpenURL; ///////////////////////////////////////////////////////////////// @@ -14,6 +18,7 @@ ///////////////////////////////////////////////////////////////// BranchObj* BranchObj::itLast=NULL; +BranchObj* BranchObj::itFirst=NULL; BranchObj::BranchObj () :OrnamentedObj() @@ -24,39 +29,50 @@ depth=-1; } -BranchObj::BranchObj (QCanvas* c):OrnamentedObj (c) +BranchObj::BranchObj (QGraphicsScene* s):OrnamentedObj (s) { -// cout << "Const BranchObj (c) called from MapCenterObj (c)\n"; - canvas=c; +// cout << "Const BranchObj (s) called from MapCenterObj (s)\n"; + parObj=NULL; + scene=s; } -BranchObj::BranchObj (QCanvas* c, LinkableMapObj* p):OrnamentedObj (c) +BranchObj::BranchObj (QGraphicsScene* s, LinkableMapObj* p):OrnamentedObj (s) { -// cout << "Const BranchObj (c,p)\n"; - canvas=c; +// cout << "Const BranchObj (s,p)\n"; + scene=s; setParObj (p); depth=p->getDepth()+1; if (depth==1) // Calc angle to mapCenter if I am a mainbranch // needed for reordering the mainbranches clockwise // around mapcenter - angle=getAngle (QPoint ((int)(x() - parObj->getChildPos().x() ), - (int)(y() - parObj->getChildPos().y() ) ) ); + angle=getAngle (QPointF (x() - parObj->getChildPos().x() , + (y() - parObj->getChildPos().y() ) ) ); init(); } BranchObj::~BranchObj () { - //cout << "Destr BranchObj\n"; + // If I'm animated, I need to un-animate myself first + if (anim.isAnimated() ) + { + anim.setAnimated (false); + mapEditor->getModel()->stopAnimation (this); + } + + + //cout << "Destr BranchObj of "<<this<<endl; // Check, if this branch was the last child to be deleted // If so, unset the scrolled flags - BranchObj *po=(BranchObj*)(parObj); + BranchObj *po=(BranchObj*)parObj; + BranchObj *bo; if (po) { - BranchObj *bo=((BranchObj*)(parObj))->getLastBranch(); - if (!bo) po->unScroll(); + bo=((BranchObj*)parObj)->getLastBranch(); + if (bo) po->unScroll(); } + clear(); } bool BranchObj::operator< ( const BranchObj & other ) @@ -69,40 +85,23 @@ return angle == other.angle; } -int BranchObjPtrList::compareItems ( QPtrCollection::Item i, QPtrCollection::Item j) -{ - // Make sure PtrList::find works - if (i==j) return 0; - - if ( ((BranchObj*)(i))->angle > ((BranchObj*)(j))->angle ) - return 1; - else - return -1; -} - void BranchObj::init () { - branch.setAutoDelete (true); - floatimage.setAutoDelete (true); + if (parObj) + { + absPos=getRandPos(); + absPos+=parObj->getChildPos(); + } - absPos=getRandPos(); - absPos+=parObj->getChildPos(); - - // TODO This should be done in TextObj later - QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0"); -// font.setPointSize(12); - heading->setFont(font ); -// heading->setText(QObject::tr("new branch")); - - lastSelectedBranch=-1; + lastSelectedBranch=0; setChildObj(this); scrolled=false; tmpUnscrolled=false; - url=""; - vymLink=""; + includeImagesVer=false; + includeImagesHor=false; } void BranchObj::copy (BranchObj* other) @@ -110,24 +109,18 @@ OrnamentedObj::copy(other); branch.clear(); - BranchObj* b; - for (b=other->branch.first(); b;b=other->branch.next() ) + for (int i=0; i<other->branch.size(); ++i) // Make deep copy of b // Because addBranch again calls copy for the childs, // Those will get a deep copy, too - addBranch(b); + addBranch(other->branch.at(i) ); - FloatImageObj *fi; - for (fi=other->floatimage.first(); fi;fi=other->floatimage.next() ) - addFloatImage (fi); - + for (int i=0; i<other->floatimage.size(); ++i) + addFloatImage (other->floatimage.at(i)); scrolled=other->scrolled; tmpUnscrolled=other->tmpUnscrolled; setVisibility (other->visible); - url=other->url; - vymLink=other->vymLink; - angle=other->angle; positionBBox(); @@ -135,26 +128,42 @@ void BranchObj::clear() { - branch.clear(); - floatimage.clear(); + setVisibility (true); + + while (!floatimage.isEmpty()) + delete floatimage.takeFirst(); + + while (!xlink.isEmpty()) + delete xlink.takeFirst(); + + while (!branch.isEmpty()) + delete branch.takeFirst(); +} + +bool isAbove (BranchObj* a, BranchObj *b) +{ + if (a->angle < b->angle) + return true; + else + return false; } int BranchObj::getNum() { if (parObj) - return ((BranchObj*)(parObj))->getNum ((BranchObj*)(this)); + return ((BranchObj*)parObj)->getNum (this); else return 0; } int BranchObj::getNum(BranchObj *bo) { - return branch.findRef (bo); + return branch.indexOf (bo); } int BranchObj::getFloatImageNum(FloatImageObj *fio) { - return floatimage.findRef (fio); + return floatimage.indexOf(fio); } int BranchObj::countBranches() @@ -167,7 +176,12 @@ return floatimage.count(); } -void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPoint m, int off) +int BranchObj::countXLinks() +{ + return xlink.count(); +} + +void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPointF m, int off) { // Temporary link to lmo // m is position of mouse pointer @@ -181,19 +195,10 @@ // ignore mapcenter and mainbranch if (lmo->getDepth()<2) off=0; if (off==0) - { link2ParPos=false; - parObj=o; - } else - { link2ParPos=true; - if (off>0) - parObj=o->getParObj(); - else - parObj=o->getParObj(); - parObj=o; - } + parObj=o; depth=parObj->getDepth()+1; @@ -207,17 +212,17 @@ if (depth==1) { // new parent is the mapcenter itself - QPoint p= normalise ( QPoint (m.x() - o->getChildPos().x(), + QPointF p= normalise ( QPointF (m.x() - o->getChildPos().x(), m.y() - o->getChildPos().y() )); if (p.x()<0) p.setX( p.x()-bbox.width() ); move2RelPos (p); } else { - int y; + qreal y; if (off==0) { // new parent is just a branch, link to it - QRect t=o->getBBoxSizeWithChilds(); + QRectF t=o->getBBoxSizeWithChilds(); if (o->getLastBranch()) y=t.y() + t.height() ; else @@ -235,14 +240,14 @@ // Don't try to find that branch, guess 12 pixels y=o->getChildPos().y() -height() + 12; } - if (o->getOrientation()==OrientLeftOfCenter) + if (o->getOrientation()==LinkableMapObj::LeftOfCenter) move ( o->getChildPos().x() - linkwidth, y ); else move (o->getChildPos().x() + linkwidth, y ); } // updateLink is called implicitly in move - reposition(); // FIXME shouldn't be this a request? + requestReposition(); } void BranchObj::unsetParObjTmp() @@ -254,6 +259,7 @@ parObjTmpBuf=NULL; depth=parObj->getDepth()+1; setLinkStyle (getDefLinkStyle() ); + updateLink(); } } @@ -265,23 +271,18 @@ void BranchObj::toggleScroll() { - BranchObj *bo; if (scrolled) { scrolled=false; systemFlags->deactivate("scrolledright"); - for (bo=branch.first(); bo; bo=branch.next() ) - { - bo->setVisibility(true); - } + for (int i=0; i<branch.size(); ++i) + branch.at(i)->setVisibility(true); } else { scrolled=true; systemFlags->activate("scrolledright"); - for (bo=branch.first(); bo; bo=branch.next() ) - { - bo->setVisibility(false); - } + for (int i=0; i<branch.size(); ++i) + branch.at(i)->setVisibility(false); } calcBBoxSize(); positionBBox(); @@ -350,18 +351,19 @@ standardFlags->setVisibility(v); LinkableMapObj::setVisibility (v); + // Only change childs, if I am not scrolled if (!scrolled && (depth < toDepth)) { // Now go recursivly through all childs - BranchObj* b; - for (b=branch.first(); b;b=branch.next() ) - b->setVisibility (v,toDepth); - FloatImageObj *fio; - for (fio=floatimage.first(); fio; fio=floatimage.next()) - fio->setVisibility (v); + int i; + for (i=0; i<branch.size(); ++i) + branch.at(i)->setVisibility (v,toDepth); + for (i=0; i<floatimage.size(); ++i) + floatimage.at(i)->setVisibility (v); + for (i=0; i<xlink.size(); ++i) + xlink.at(i)->setVisibility (); } } // depth <= toDepth - move (absPos.x(), absPos.y() ); requestReposition(); } @@ -376,53 +378,60 @@ // Overloaded from LinkableMapObj // BranchObj can use color of heading - if (mapEditor->getLinkColorHint()==HeadingColor) - LinkableMapObj::setLinkColor (heading->getColor() ); - else - LinkableMapObj::setLinkColor (); + if (mapEditor) + { + if (mapEditor->getMapLinkColorHint()==HeadingColor) + LinkableMapObj::setLinkColor (heading->getColor() ); + else + LinkableMapObj::setLinkColor (); + } } -void BranchObj::setColor (QColor col, bool colorChilds) +void BranchObj::setColorSubtree(QColor col) { - heading->setColor(col); - setLinkColor(); - if (colorChilds) - { - BranchObj *bo; - for (bo=branch.first(); bo; bo=branch.next() ) - bo->setColor(col,colorChilds); - } + setColor (col); + for (int i=0; i<branch.size(); ++i) + branch.at(i)->setColorSubtree(col); } - BranchObj* BranchObj::first() { itLast=NULL; + itFirst=this; return this; } BranchObj* BranchObj::next() { + BranchObj *bo; BranchObj *lmo; - BranchObj *bo=branch.first(); - BranchObj *po=(BranchObj*)(parObj); + BranchObj *po=(BranchObj*)parObj; + + if (branch.isEmpty()) + bo=NULL; + else + bo=branch.first(); if (!itLast) - { // We are just beginning at the mapCenter + { + // no itLast, we are just beginning if (bo) { + // we have childs, return first one itLast=this; return bo; } else { - itLast=NULL; + // No childs, so there is no next + itLast=this; return NULL; } } - if (itLast==parObj) - { // We come from above + // We have an itLast + if (itLast==po) + { // We come from parent if (bo) { // there are childs, go there @@ -433,7 +442,7 @@ { // no childs, try to go up again if (po) { - // go up + // go back to parent and try to find next there itLast=this; lmo=po->next(); itLast=this; @@ -442,22 +451,35 @@ } else { - // can't go up, I am mapCenter + // can't go up, I am mapCenter, no next itLast=NULL; return NULL; } } } - // Try to find last child, we came from, in my own childs + // We don't come from parent, but from brother or childs + + // Try to find last child, where we came from, in my own childs bool searching=true; - while (bo && searching) + int i=0; + while (i<branch.size()) { - if (itLast==bo) searching=false; - bo=branch.next(); + // Try to find itLast in my own childs + if (itLast==branch.at(i)) + { + // ok, we come from my own childs + if (i<branch.size()-1) + bo=branch.at(i+1); + else + bo=NULL; + searching=false; + i=branch.size(); + } + ++i; } if (!searching) - { // found lastLMO in my childs + { // found itLast in my childs if (bo) { // found a brother of lastLMO @@ -468,6 +490,7 @@ { if (po) { + if (this==itFirst) return NULL; // Stop at starting point // go up itLast=this; lmo=po->next(); @@ -484,12 +507,11 @@ } // couldn't find last child, it must be a nephew of mine - bo=branch.first(); - if (bo) + if (branch.size()>0) { // proceed with my first child itLast=this; - return bo; + return branch.first(); } else { @@ -521,14 +543,22 @@ itLast=it; } +void BranchObj::positionContents() +{ + for (int i=0; i<floatimage.size(); ++i ) + floatimage.at(i)->reposition(); + OrnamentedObj::positionContents(); +} void BranchObj::move (double x, double y) { OrnamentedObj::move (x,y); + for (int i=0; i<floatimage.size(); ++i ) + floatimage.at(i)->reposition(); positionBBox(); } -void BranchObj::move (QPoint p) +void BranchObj::move (QPointF p) { move (p.x(), p.y()); } @@ -536,13 +566,12 @@ void BranchObj::moveBy (double x, double y) { OrnamentedObj::moveBy (x,y); + for (int i=0; i<branch.size(); ++i) + branch.at(i)->moveBy (x,y); positionBBox(); - BranchObj* b; - for (b=branch.first(); b;b=branch.next() ) - b->moveBy (x,y); } - -void BranchObj::moveBy (QPoint p) + +void BranchObj::moveBy (QPointF p) { moveBy (p.x(), p.y()); } @@ -550,38 +579,31 @@ void BranchObj::positionBBox() { - - heading->positionBBox(); - systemFlags->positionBBox(); - standardFlags->positionBBox(); - // It seems that setting x,y also affects width,height - int w_old=bbox.width(); - int h_old=bbox.height(); - bbox.setX (absPos.x() ); - bbox.setY (absPos.y() ); - bbox.setWidth(w_old); - bbox.setHeight(h_old); - - - setSelBox(); + QPointF ap=getAbsPos(); + bbox.moveTopLeft (ap); + positionContents(); // set the frame - frame->setRect(QRect(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) ); + frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) ); + + // Update links to other branches + for (int i=0; i<xlink.size(); ++i) + xlink.at(i)->updateXLink(); } void BranchObj::calcBBoxSize() { - QSize heading_r=heading->getSize(); - int heading_w=static_cast <int> (heading_r.width() ); - int heading_h=static_cast <int> (heading_r.height() ); - QSize sysflags_r=systemFlags->getSize(); - int sysflags_h=sysflags_r.height(); - int sysflags_w=sysflags_r.width(); - QSize stanflags_r=standardFlags->getSize(); - int stanflags_h=stanflags_r.height(); - int stanflags_w=stanflags_r.width(); - int w; - int h; + QSizeF heading_r=heading->getSize(); + qreal heading_w=(qreal) heading_r.width() ; + qreal heading_h=(qreal) heading_r.height() ; + QSizeF sysflags_r=systemFlags->getSize(); + qreal sysflags_h=sysflags_r.height(); + qreal sysflags_w=sysflags_r.width(); + QSizeF stanflags_r=standardFlags->getSize(); + qreal stanflags_h=stanflags_r.height(); + qreal stanflags_w=stanflags_r.width(); + qreal w; + qreal h; // set width to sum of all widths w=heading_w + sysflags_w + stanflags_w; @@ -589,106 +611,186 @@ h=max (sysflags_h,stanflags_h); h=max (h,heading_h); - w+=frame->getBorder(); - h+=frame->getBorder(); - bbox.setSize (QSize (w,h)); + // Save the dimension of flags and heading + ornamentsBBox.setSize ( QSizeF(w,h)); + + // clickBox includes Flags and Heading + clickBox.setSize (ornamentsBBox.size() ); + + // Floatimages + QPointF rp; + + topPad=botPad=leftPad=rightPad=0; + if (includeImagesVer || includeImagesHor) + { + if (countFloatImages()>0) + { + for (int i=0; i<floatimage.size(); ++i ) + { + rp=floatimage.at(i)->getRelPos(); + if (includeImagesVer) + { + if (rp.y() < 0) + topPad=max (topPad,-rp.y()-h); + if (rp.y()+floatimage.at(i)->height() > 0) + botPad=max (botPad,rp.y()+floatimage.at(i)->height()); + } + if (includeImagesHor) + { + if (orientation==LinkableMapObj::RightOfCenter) + { + if (-rp.x()-w > 0) + leftPad=max (leftPad,-rp.x()-w); + if (rp.x()+floatimage.at(i)->width() > 0) + rightPad=max (rightPad,rp.x()+floatimage.at(i)->width()); + } else + { + if (rp.x()< 0) + leftPad=max (leftPad,-rp.x()); + if (rp.x()+floatimage.at(i)->width() > w) + rightPad=max (rightPad,rp.x()+floatimage.at(i)->width()-w); + } + } + } + } + h+=topPad+botPad; + w+=leftPad+rightPad; + } + + // Frame thickness + w+=frame->getPadding(); + h+=frame->getPadding(); + + // Finally set size + bbox.setSize (QSizeF (w,h)); } -LinkableMapObj* BranchObj::findMapObj(QPoint p, LinkableMapObj* excludeLMO) +void BranchObj::setDockPos() +{ + // Sets childpos and parpos depending on orientation + if (getOrientation()==LinkableMapObj::LeftOfCenter ) + { + childPos=QPointF ( + ornamentsBBox.bottomLeft().x(), + bottomlineY); + parPos=QPointF ( + ornamentsBBox.bottomRight().x(), + bottomlineY); + } else + { + childPos=QPointF ( + ornamentsBBox.bottomRight().x(), + bottomlineY); + parPos=QPointF ( + ornamentsBBox.bottomLeft().x(), + bottomlineY); + } +} + +LinkableMapObj* BranchObj::findMapObj(QPointF p, LinkableMapObj* excludeLMO) { // Search branches - BranchObj *b; LinkableMapObj *lmo; - for (b=branch.first(); b; b=branch.next() ) + for (int i=0; i<branch.size(); ++i) { - lmo=b->findMapObj(p, excludeLMO); + lmo=branch.at(i)->findMapObj(p, excludeLMO); + if (lmo != NULL) return lmo; + } + + + // Search myself + if (inBox (p,clickBox) && (this != excludeLMO) && isVisibleObj() ) + return this; + + // Search float images + for (int i=0; i<floatimage.size(); ++i ) + if (inBox(p,floatimage.at(i)->getClickBox()) && + (floatimage.at(i) != excludeLMO) && + floatimage.at(i)->getParObj()!= excludeLMO && + floatimage.at(i)->isVisibleObj() + ) return floatimage.at(i); + + return NULL; +} + +LinkableMapObj* BranchObj::findID (QString sid) +{ + // Search branches + LinkableMapObj *lmo; + for (int i=0; i<branch.size(); ++i) + { + lmo=branch.at(i)->findID (sid); if (lmo != NULL) return lmo; } // Search myself - if (inBBox (p) && (this != excludeLMO) && isVisibleObj() ) - return this; + if (sid==objID) return this; + +/* // Search float images - FloatImageObj *foi; - for (foi=floatimage.first(); foi; foi=floatimage.next() ) - if (foi->inBBox(p) && (foi != excludeLMO) && foi->getParObj()!= excludeLMO) return foi; - + for (int i=0; i<floatimage.size(); ++i ) + if (floatimage.at(i)->inBox(p) && + (floatimage.at(i) != excludeLMO) && + floatimage.at(i)->getParObj()!= excludeLMO && + floatimage.at(i)->isVisibleObj() + ) return floatimage.at(i); +*/ return NULL; } void BranchObj::setHeading(QString s) { - // Adjusting font size - QFont font=heading->getFont(); - if (depth==0) - font.setPointSize(16); - else - if (depth>1) - font.setPointSize(10); - else - font.setPointSize(12); - heading->setFont(font); heading->setText(s); // set new heading calcBBoxSize(); // recalculate bbox positionBBox(); // rearrange contents requestReposition(); } -void BranchObj::setURL(QString s) +void BranchObj::setHideTmp (HideTmpMode mode) { - url=s; - if (!url.isEmpty()) - systemFlags->activate("url"); - else - systemFlags->deactivate("url"); - calcBBoxSize(); // recalculate bbox - positionBBox(); // rearrange contents - forceReposition(); + if (mode==HideExport && (hideExport|| hasHiddenExportParent() ) ) + { + // Hide stuff according to hideExport flag and parents + setVisibility (false); + hidden=true; + }else + { + // Do not hide, but still take care of scrolled status + if (hasScrolledParent(this)) + setVisibility (false); + else + setVisibility (true); + hidden=false; + } + + // And take care of my childs + for (int i=0; i<branch.size(); ++i) + branch.at(i)->setHideTmp (mode); } -QString BranchObj::getURL() +bool BranchObj::hasHiddenExportParent() { - return url; + // Calls parents recursivly to + // find out, if we or parents are temp. hidden + + if (hidden || hideExport) return true; + + BranchObj* bo=(BranchObj*)parObj; + if (bo) + return bo->hasHiddenExportParent(); + else + return false; } -void BranchObj::setVymLink(QString s) +QString BranchObj::saveToDir (const QString &tmpdir,const QString &prefix, const QPointF& offset) { - if (!s.isEmpty()) - { - // We need the relative (from loading) - // or absolute path (from User event) - // and build the absolute path. - // Note: If we have relative, use path of - // current map to build absolute path - QDir d(s); - if (!d.path().startsWith ("/")) - { - QString p=mapEditor->getDestPath(); - int i=p.findRev("/",-1); - d.setPath(p.left(i)+"/"+s); - d.convertToAbs(); - } - vymLink=d.path(); - systemFlags->activate("vymLink"); - } - else - { - systemFlags->deactivate("vymLink"); - vymLink=""; - } - calcBBoxSize(); // recalculate bbox - positionBBox(); // rearrange contents - forceReposition(); -} + // Cloudy stuff can be hidden during exports + if (hidden) return ""; -QString BranchObj::getVymLink() -{ - return vymLink; -} - -QString BranchObj::saveToDir (const QString &tmpdir,const QString &prefix, const QPoint& offset) -{ + // Update of note is usually done while unselecting a branch + if (isNoteInEditor) getNoteFromTextEditor(); + QString s,a; QString scrolledAttr; if (scrolled) @@ -696,90 +798,192 @@ else scrolledAttr=""; - QString posAttr; - if (depth<2) posAttr= - attribut("absPosX",QString().setNum(absPos.x(),10)) + - attribut("absPosY",QString().setNum(absPos.y(),10)); - else - posAttr=""; - - QString urlAttr; - if (!url.isEmpty()) - urlAttr=attribut ("url",url); - - QString vymLinkAttr; - if (!vymLink.isEmpty()) - vymLinkAttr=attribut ("vymLink",convertToRel(mapEditor->getDestPath(),vymLink) ); - - QString frameAttr; - if (frame->getFrameType()!=NoFrame) - frameAttr=attribut ("frameType",frame->getFrameTypeName()); - else - frameAttr=""; - // save area, if not scrolled QString areaAttr; if (!((BranchObj*)(parObj))->isScrolled() ) { areaAttr= - attribut("x1",QString().setNum(absPos.x()-offset.x(),10)) + - attribut("y1",QString().setNum(absPos.y()-offset.y(),10)) + - attribut("x2",QString().setNum(absPos.x()+width()-offset.x(),10)) + - attribut("y2",QString().setNum(absPos.y()+height()-offset.y(),10)); + attribut("x1",QString().setNum(absPos.x()-offset.x())) + + attribut("y1",QString().setNum(absPos.y()-offset.y())) + + attribut("x2",QString().setNum(absPos.x()+width()-offset.x())) + + attribut("y2",QString().setNum(absPos.y()+height()-offset.y())); } else areaAttr=""; - s=beginElement ("branch" +scrolledAttr +posAttr +urlAttr +vymLinkAttr +frameAttr +areaAttr); + // Providing an ID for a branch makes export to XHTML easier + QString idAttr; + if (countXLinks()>0) + idAttr=attribut ("id",mapEditor->getModel()->getSelectString(this)); //TODO directly access model + else + idAttr=""; + + s=beginElement ("branch" + +getOrnXMLAttr() + +scrolledAttr + +areaAttr + +idAttr + +getIncludeImageAttr() ); incIndent(); // save heading - s=s+valueElement("heading", getHeading(), + s+=valueElement("heading", getHeading(), attribut ("textColor",QColor(heading->getColor()).name())); + // Save frame + if (frame->getFrameType()!=FrameObj::NoFrame) + s+=frame->saveToDir (); + // save names of flags set s+=standardFlags->saveToDir(tmpdir,prefix,0); + // Save FloatImages + for (int i=0; i<floatimage.size(); ++i) + s+=floatimage.at(i)->saveToDir (tmpdir,prefix); + // save note if (!note.isEmpty() ) s+=note.saveToDir(); // Save branches - BranchObj *bo; - for (bo=branch.first(); bo; bo=branch.next() ) - s+=bo->saveToDir(tmpdir,prefix,offset); + for (int i=0; i<branch.size(); ++i) + s+=branch.at(i)->saveToDir(tmpdir,prefix,offset); + + // Save XLinks + QString ol; // old link + QString cl; // current link + for (int i=0; i<xlink.size(); ++i) + { + cl=xlink.at(i)->saveToDir(); + if (cl!=ol) + { + s+=cl; + ol=cl; + } else + { + qWarning (QString("Ignoring of duplicate xLink in %1").arg(getHeading())); + } + } + decIndent(); - - // Save FloatImages - FloatImageObj *fio; - for (fio=floatimage.first(); fio; fio=floatimage.next() ) - s+=fio->saveToDir (tmpdir,prefix); - s+=endElement ("branch"); return s; } -LinkableMapObj* BranchObj::addFloatImage () +void BranchObj::addXLink (XLinkObj *xlo) { - FloatImageObj *newfi=new FloatImageObj (canvas,this); + xlink.append (xlo); + +} + +void BranchObj::removeXLinkRef (XLinkObj *xlo) +{ + xlink.removeAt (xlink.indexOf(xlo)); +} + +void BranchObj::deleteXLink(XLinkObj *xlo) +{ + xlo->deactivate(); + if (!xlo->isUsed()) delete (xlo); +} + +void BranchObj::deleteXLinkAt (int i) +{ + XLinkObj *xlo=xlink.at(i); + xlo->deactivate(); + if (!xlo->isUsed()) delete(xlo); +} + +XLinkObj* BranchObj::XLinkAt (int i) +{ + return xlink.at(i); +} + +int BranchObj::countXLink() +{ + return xlink.count(); +} + + +BranchObj* BranchObj::XLinkTargetAt (int i) +{ + if (i>=0 && i<xlink.size()) + { + if (xlink.at(i)) + return xlink.at(i)->otherBranch (this); + } + return NULL; +} + +void BranchObj::setIncludeImagesVer(bool b) +{ + includeImagesVer=b; + calcBBoxSize(); + positionBBox(); + requestReposition(); +} + +bool BranchObj::getIncludeImagesVer() +{ + return includeImagesVer; +} + +void BranchObj::setIncludeImagesHor(bool b) +{ + includeImagesHor=b; + calcBBoxSize(); + positionBBox(); + requestReposition(); +} + +bool BranchObj::getIncludeImagesHor() +{ + return includeImagesHor; +} + +QString BranchObj::getIncludeImageAttr() +{ + QString a; + if (includeImagesVer) + a=attribut ("incImgV","true"); + else + a=attribut ("incImgV","false"); + if (includeImagesHor) + a+=attribut ("incImgH","true"); + else + a+=attribut ("incImgH","false"); + return a; +} + +FloatImageObj* BranchObj::addFloatImage () +{ + FloatImageObj *newfi=new FloatImageObj (scene,this); floatimage.append (newfi); if (hasScrolledParent(this) ) newfi->setVisibility (false); else newfi->setVisibility(visible); + /* + calcBBoxSize(); + positionBBox(); + */ requestReposition(); return newfi; } -LinkableMapObj* BranchObj::addFloatImage (FloatImageObj *fio) +FloatImageObj* BranchObj::addFloatImage (FloatImageObj *fio) { - FloatImageObj *newfi=new FloatImageObj (canvas,this); + FloatImageObj *newfi=new FloatImageObj (scene,this); floatimage.append (newfi); newfi->copy (fio); if (hasScrolledParent(this) ) newfi->setVisibility (false); else newfi->setVisibility(visible); + /* + calcBBoxSize(); + positionBBox(); + */ requestReposition(); return newfi; } @@ -801,62 +1005,92 @@ void BranchObj::removeFloatImage (FloatImageObj *fio) { - floatimage.remove (fio); + int i=floatimage.indexOf (fio); + if (i>-1) delete (floatimage.takeAt (i)); + calcBBoxSize(); + positionBBox(); requestReposition(); } void BranchObj::savePosInAngle () { // Save position in angle - BranchObj *b; - int i=0; - for (b=branch.first(); b; b=branch.next() ) + for (int i=0; i<branch.size(); ++i) + branch.at(i)->angle=i; +} + +void BranchObj::setDefAttr (BranchModification mod) +{ + int fontsize; + switch (depth) { - b->angle=i; - i++; - } + case 0: fontsize=16; break; + case 1: fontsize=12; break; + default: fontsize=10; break; + } + + setLinkColor (); + setLinkStyle(getDefLinkStyle()); + QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0"); + font.setPointSize(fontsize); + heading->setFont(font ); + + if (mod==NewBranch) + setColor (((BranchObj*)(parObj))->getColor()); + + calcBBoxSize(); } BranchObj* BranchObj::addBranch() { - BranchObj* newbo=new BranchObj(canvas,this); + BranchObj* newbo=new BranchObj(scene,this); branch.append (newbo); newbo->setParObj(this); - newbo->setColor(getColor(),false); - newbo->setLinkColor(); + newbo->setDefAttr(NewBranch); newbo->setHeading ("new"); - newbo->setLinkStyle (newbo->getDefLinkStyle()); if (scrolled) newbo->setVisibility (false); else newbo->setVisibility(visible); + newbo->updateLink(); requestReposition(); return newbo; } BranchObj* BranchObj::addBranch(BranchObj* bo) { - BranchObj* newbo=new BranchObj(canvas,this); + BranchObj* newbo=new BranchObj(scene,this); branch.append (newbo); newbo->copy(bo); newbo->setParObj(this); - newbo->setHeading (newbo->getHeading()); // adjust fontsize to depth - newbo->setLinkStyle (newbo->getDefLinkStyle()); + newbo->setDefAttr(MovedBranch); if (scrolled) newbo->setVisibility (false); else newbo->setVisibility(bo->visible); + newbo->updateLink(); requestReposition(); return newbo; } +BranchObj* BranchObj::addBranchPtr(BranchObj* bo) +{ + branch.append (bo); + bo->setParObj (this); + bo->depth=depth+1; + bo->setDefAttr(MovedBranch); + if (scrolled) tmpUnscroll(); + setLastSelectedBranch (bo); + return bo; +} + BranchObj* BranchObj::insertBranch(int pos) { savePosInAngle(); // Add new bo and resort branches BranchObj *newbo=addBranch (); newbo->angle=pos-0.5; - branch.sort(); + qSort (branch.begin(),branch.end(), isAbove); return newbo; } @@ -866,133 +1100,288 @@ // Add new bo and resort branches bo->angle=pos-0.5; BranchObj *newbo=addBranch (bo); - branch.sort(); + qSort (branch.begin(),branch.end(), isAbove); return newbo; } +BranchObj* BranchObj::insertBranchPtr (BranchObj* bo, int pos) +{ + savePosInAngle(); + // Add new bo and resort branches + bo->angle=pos-0.5; + branch.append (bo); + bo->setParObj (this); + bo->depth=depth+1; + bo->setDefAttr (MovedBranch); + if (scrolled) tmpUnscroll(); + setLastSelectedBranch (bo); + qSort (branch.begin(),branch.end(), isAbove); + return bo; +} + +void BranchObj::removeBranchHere(BranchObj* borem) +{ + // This removes the branch bo from list, but + // inserts its childs at the place of bo + BranchObj *bo; + bo=borem->getLastBranch(); + int pos=borem->getNum(); + while (bo) + { + bo->linkTo (this,pos+1); + bo=borem->getLastBranch(); + } + removeBranch (borem); +} + +void BranchObj::removeChilds() +{ + clear(); +} + void BranchObj::removeBranch(BranchObj* bo) { // if bo is not in branch remove returns false, we // don't care... - branch.remove (bo); + + int i=branch.indexOf(bo); + if (i>=0) + { + delete (bo); + branch.removeAt (i); + } else + qWarning ("BranchObj::removeBranch tried to remove non existing branch?!\n"); + requestReposition(); +} + +void BranchObj::removeBranchPtr(BranchObj* bo) +{ + int i=branch.indexOf(bo); + + if (i>=0) + branch.removeAt (i); + else + qWarning ("BranchObj::removeBranchPtr tried to remove non existing branch?!\n"); requestReposition(); } void BranchObj::setLastSelectedBranch (BranchObj* bo) { - lastSelectedBranch=branch.find(bo); + lastSelectedBranch=branch.indexOf(bo); } BranchObj* BranchObj::getLastSelectedBranch () { - if (lastSelectedBranch>=0) + if (lastSelectedBranch>=0) { - BranchObj* bo=branch.at(lastSelectedBranch); - if (bo) return bo; - } - return branch.first(); + if ( branch.size()>lastSelectedBranch) + return branch.at(lastSelectedBranch); + if (branch.size()>0) + return branch.last(); + } + return NULL; } BranchObj* BranchObj::getFirstBranch () { - return branch.first(); + if (branch.size()>0) + return branch.first(); + else + return NULL; } BranchObj* BranchObj::getLastBranch () { - return branch.last(); + if (branch.size()>0) + return branch.last(); + else + return NULL; } -BranchObj* BranchObj::getBranchNum (const uint &i) +BranchObj* BranchObj::getBranchNum (int i) { - return branch.at(i); + if (i>=0 && i<branch.size()) + return branch.at(i); + else + return NULL; } +bool BranchObj::canMoveBranchUp() +{ + if (!parObj || depth==1) return false; + BranchObj* par=(BranchObj*)parObj; + if (this==par->getFirstBranch()) + return false; + else + return true; +} -BranchObj* BranchObj::moveBranchUp(BranchObj* bo1) // move a branch up (modify myself) +BranchObj* BranchObj::moveBranchUp(BranchObj* bo1) // modify my childlist { savePosInAngle(); - int i=branch.find(bo1); + int i=branch.indexOf(bo1); if (i>0) { // -1 if bo1 not found branch.at(i)->angle--; branch.at(i-1)->angle++; - branch.sort(); - return branch.at(i-1); + qSort (branch.begin(),branch.end(), isAbove); + return branch.at(i); } else - return branch.at(i); + return NULL; } -BranchObj* BranchObj::moveBranchDown(BranchObj* bo1) +bool BranchObj::canMoveBranchDown() +{ + if (!parObj|| depth==1) return false; + BranchObj* par=(BranchObj*)parObj; + if (this==par->getLastBranch()) + return false; + else + return true; +} + +BranchObj* BranchObj::moveBranchDown(BranchObj* bo1)// modify my childlist { savePosInAngle(); - int i=branch.find(bo1); + int i=branch.indexOf(bo1); int j; - if (branch.next()) + if (i <branch.size()) { - j = branch.at(); + j = i+1; branch.at(i)->angle++; branch.at(j)->angle--; - branch.sort(); - return branch.at(j); + qSort (branch.begin(),branch.end(), isAbove); + return branch.at(i); } else - return branch.at(i); + return NULL; } -void BranchObj::alignRelativeTo (QPoint ref) +void BranchObj::sortChildren() { -/* FIXME testing - if (!getHeading().isEmpty()) - cout << "BO::alignRelTo "<<getHeading()<<endl; - else - cout << "BO::alignRelTo ???"<<endl; - cout << " d="<<depth<<endl; -*/ - int th = bboxTotal.height(); + int childCount=branch.count(); + int curChildIndex; + bool madeChanges=false; + do + { + madeChanges=false; + for(curChildIndex=1;curChildIndex<childCount;curChildIndex++){ + BranchObj* curChild=(BranchObj*)branch.at(curChildIndex); + BranchObj* prevChild=(BranchObj*)branch.at(curChildIndex-1); + if(prevChild->heading->text().compare(curChild->heading->text())>0) + { + this->moveBranchUp(curChild); + madeChanges=true; + } + } + }while(madeChanges); +} - // If I am the mapcenter or a mainbranch, reposition heading + +BranchObj* BranchObj::linkTo (BranchObj* dst, int pos) +{ + // Find current parent and + // remove pointer to myself there + if (!dst) return NULL; + BranchObj *par=(BranchObj*)parObj; + if (par) + par->removeBranchPtr (this); + else + return NULL; + + // Create new pointer to myself at dst + if (pos<0||dst->getDepth()==0) + { + // links myself as last branch at dst + dst->addBranchPtr (this); + updateLink(); + return this; + } else + { + // inserts me at pos in parent of dst + if (par) + { + BranchObj *bo=dst->insertBranchPtr (this,pos); + bo->setDefAttr(MovedBranch); + updateLink(); + return bo; + + } else + return NULL; + } +} + +void BranchObj::alignRelativeTo (QPointF ref) +{ + qreal th = bboxTotal.height(); +// TODO testing +/* + QPointF pp; if (parObj) pp=parObj->getChildPos(); + cout << "BO::alignRelTo "<<qPrintable (getHeading()); + cout << " d="<<depth<< + " ref="<<ref<< +// " bbox.topLeft="<<bboxTotal.topLeft()<< + " absPos="<<absPos<< + " relPos="<<relPos<< + " parPos="<<pp<< + " orient="<<orientation<< +// " pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<< +// " hidden="<<hidden<< +// " th="<<th<< + endl; +*/ + + setOrientation(); + //updateLink(); + if (depth<2) { - move (absPos.x(),absPos.y()); if (depth==1) { + // Position relatively, if needed + //if (useRelPos) move2RelPos (relPos.x(), relPos.y()); + // Calc angle to mapCenter if I am a mainbranch // needed for reordering the mainbranches clockwise // around mapcenter - angle=getAngle (QPoint ((int)(x() - parObj->getChildPos().x() ), + angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ), (int)(y() - parObj->getChildPos().y() ) ) ); - } + } } else { // Align myself depending on orientation and parent, but - // only if I am not the mainbranch or mapcenter itself - switch (orientation) + // only if I am not a mainbranch or mapcenter itself + + if (anim.isAnimated()) { - case OrientLeftOfCenter: - move (ref.x()-bbox.width(), ref.y() + (th-bbox.height())/2 ); - break; - case OrientRightOfCenter: - move (ref.x(), ref.y() + (th-bbox.height())/2 ); - break; - default: - cout <<"LMO::alignRelativeTo: oops, no orientation given...\n"; - break; - } + move2RelPos(anim); + } else + { + LinkableMapObj::Orientation o; + o=parObj->getOrientation(); + switch (orientation) + { + case LinkableMapObj::LeftOfCenter: + move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 ); + break; + case LinkableMapObj::RightOfCenter: + move (ref.x() , ref.y() + (th-bbox.height())/2 ); + break; + default: + qWarning ("LMO::alignRelativeTo: oops, no orientation given..."); + break; + } + } } - FloatImageObj *fio; - for (fio=floatimage.first(); fio; fio=floatimage.next() ) - fio->reposition(); - if (scrolled) return; // Set reference point for alignment of childs - QPoint ref2; - if (orientation==OrientLeftOfCenter) - ref2.setX(childPos.x() - linkwidth); + QPointF ref2; + if (orientation==LinkableMapObj::LeftOfCenter) + ref2.setX(bbox.topLeft().x() - linkwidth); else - ref2.setX(childPos.x() + linkwidth); + ref2.setX(bbox.topRight().x() + linkwidth); if (depth==1) ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2); @@ -1000,73 +1389,111 @@ ref2.setY(ref.y() ); // Align the childs depending on reference point - BranchObj *b; - for (b=branch.first(); b; b=branch.next() ) + for (int i=0; i<branch.size(); ++i) { - b->alignRelativeTo (ref2); - ref2.setY(ref2.y() + b->getBBoxSizeWithChilds().height() ); + if (!branch.at(i)->isHidden()) + { + branch.at(i)->alignRelativeTo (ref2); + ref2.setY(ref2.y() + branch.at(i)->getBBoxSizeWithChilds().height() ); + } } } void BranchObj::reposition() { -/* FIXME testing +/* TODO testing only if (!getHeading().isEmpty()) - cout << "BO::reposition "<<getHeading()<<endl; + cout << "BO::reposition "<<qPrintable(getHeading())<<endl; else cout << "BO::reposition ???"<<endl; + + cout << " orient="<<orientation<<endl; */ + if (depth==0) { // only calculate the sizes once. If the deepest LMO // changes its height, // all upper LMOs have to change, too. calcBBoxSizeWithChilds(); - alignRelativeTo ( QPoint (absPos.x(), + updateLink(); // This update is needed if the scene is resized + // due to excessive moving of a FIO + + alignRelativeTo ( QPointF (absPos.x(), absPos.y()-(bboxTotal.height()-bbox.height())/2) ); - branch.sort(); + qSort (branch.begin(),branch.end(), isAbove); + positionBBox(); // Reposition bbox and contents } else { // This is only important for moving branches: // For editing a branch it isn't called... - alignRelativeTo ( QPoint (absPos.x(), + alignRelativeTo ( QPointF (absPos.x(), absPos.y()-(bboxTotal.height()-bbox.height())/2) ); } } +void BranchObj::unsetAllRepositionRequests() +{ + repositionRequest=false; + for (int i=0; i<branch.size(); ++i) + branch.at(i)->unsetAllRepositionRequests(); +} -QRect BranchObj::getTotalBBox() + +QPolygonF BranchObj::shape() { - QRect r=bbox; + QPolygonF p; + + QRectF r=getTotalBBox(); + if (orientation==LinkableMapObj::LeftOfCenter) + p <<r.bottomLeft() + <<r.topLeft() + <<QPointF (bbox.topLeft().x(), r.topLeft().y() ) + <<bbox.topRight() + <<bbox.bottomRight() + <<QPointF (bbox.bottomLeft().x(), r.bottomLeft().y() ) ; + else + p <<r.bottomRight() + <<r.topRight() + <<QPointF (bbox.topRight().x(), r.topRight().y() ) + <<bbox.topLeft() + <<bbox.bottomLeft() + <<QPointF (bbox.bottomRight().x(), r.bottomRight().y() ) ; + return p; +} + +QRectF BranchObj::getTotalBBox() +{ + QRectF r=bbox; if (scrolled) return r; - BranchObj* b; - for (b=branch.first();b ;b=branch.next() ) - r=addBBox(b->getTotalBBox(),r); + for (int i=0; i<branch.size(); ++i) + if (!branch.at(i)->isHidden()) + r=addBBox(branch.at(i)->getTotalBBox(),r); - FloatImageObj* fio; - for (fio=floatimage.first();fio ;fio=floatimage.next() ) - r=addBBox(fio->getTotalBBox(),r); + for (int i=0; i<floatimage.size(); ++i) + if (!floatimage.at(i)->isHidden()) + r=addBBox(floatimage.at(i)->getTotalBBox(),r); return r; } -QRect BranchObj::getBBoxSizeWithChilds() +QRectF BranchObj::getBBoxSizeWithChilds() { return bboxTotal; } void BranchObj::calcBBoxSizeWithChilds() -{ - // This is called only from reposition and +{ + // This is initially called only from reposition and // and only for mapcenter. So it won't be // called more than once for a single user // action + // Calculate size of LMO including all childs (to align them later) - bboxTotal.setX(bbox.x() ); bboxTotal.setY(bbox.y() ); @@ -1078,20 +1505,38 @@ return; } - QRect r(0,0,0,0); - QRect br; + if (hidden) + { + bboxTotal.setWidth (0); + bboxTotal.setHeight(0); + if (parObj) + { + bboxTotal.setX (parObj->x()); + bboxTotal.setY (parObj->y()); + } else + { + bboxTotal.setX (bbox.x()); + bboxTotal.setY (bbox.y()); + } + return; + } + + QRectF r(0,0,0,0); + QRectF br; // Now calculate recursivly // sum of heights // maximum of widths // minimum of y - BranchObj* b; - for (b=branch.first();b ;b=branch.next() ) + for (int i=0; i<branch.size(); ++i) { - b->calcBBoxSizeWithChilds(); - br=b->getBBoxSizeWithChilds(); - r.setWidth( max (br.width(), r.width() )); - r.setHeight(br.height() + r.height() ); - if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y()); + if (!branch.at(i)->isHidden()) + { + branch.at(i)->calcBBoxSizeWithChilds(); + br=branch.at(i)->getBBoxSizeWithChilds(); + r.setWidth( max (br.width(), r.width() )); + r.setHeight(br.height() + r.height() ); + if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y()); + } } // Add myself and also // add width of link to sum if necessary @@ -1099,13 +1544,25 @@ bboxTotal.setWidth (bbox.width() + r.width() ); else bboxTotal.setWidth (bbox.width() + r.width() + linkwidth); - bboxTotal.setHeight(max (r.height(), bbox.height() ) ); -// frame->setRect(QRect(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) ); + + bboxTotal.setHeight(max (r.height(), bbox.height())); } void BranchObj::select() { + // update NoteEditor + textEditor->setText(note.getNote() ); + QString fnh=note.getFilenameHint(); + if (fnh!="") + textEditor->setFilenameHint(note.getFilenameHint() ); + else + textEditor->setFilenameHint(getHeading() ); + textEditor->setFontHint (note.getFontHint() ); + isNoteInEditor=true; + + // set selected and visible LinkableMapObj::select(); + // Tell parent that I am selected now: BranchObj* po=(BranchObj*)(parObj); if (po) // TODO Try to get rid of this cast... @@ -1114,13 +1571,6 @@ // temporary unscroll, if we have scrolled parents somewhere if (parObj) ((BranchObj*)(parObj))->tmpUnscroll(); - // set Text in Editor - textEditor->setText(note.getNote() ); - textEditor->setFilename(note.getFilenameHint() ); - textEditor->setFontHint (note.getFontHint() ); - connect (textEditor, SIGNAL (textHasChanged() ), this, SLOT (updateNoteFlag() ) ); - connect (textEditor, SIGNAL (fontSizeHasChanged() ), this, SLOT (updateNoteFlag() ) ); - // Show URL and link in statusbar QString status; if (!url.isEmpty()) status+="URL: "+url+" "; @@ -1128,15 +1578,9 @@ if (!status.isEmpty()) mainWindow->statusMessage (status); // Update Toolbar - standardFlags->updateToolBar(); + updateFlagsToolbar(); - // Update Browserbutton - if (!url.isEmpty()) - actionEditOpenURL->setEnabled (true); - else - actionEditOpenURL->setEnabled (false); - - // Update actions in mapeditor + // Update actions mapEditor->updateActions(); } @@ -1146,39 +1590,38 @@ // Delete any messages like vymLink in StatusBar mainWindow->statusMessage (""); - // save note from editor and set flag - // text is done by updateNoteFlag(), just save - // filename here - note.setFilenameHint (textEditor->getFilename()); + // Save current note + if (isNoteInEditor) getNoteFromTextEditor(); + isNoteInEditor=false; // reset temporary unscroll, if we have scrolled parents somewhere if (parObj) ((BranchObj*)(parObj))->resetTmpUnscroll(); - // Disconnect textEditor from this LMO - disconnect( textEditor, SIGNAL(textHasChanged()), 0, 0 ); - disconnect( textEditor, SIGNAL (fontSizeHasChanged()),0,0 ); - // Erase content of editor textEditor->setInactive(); // unselect all buttons in toolbar - standardFlagsDefault->updateToolBar(); + standardFlagsDefault->updateToolbar(); } QString BranchObj::getSelectString() { - QString s; - if (parObj) - { - if (parObj->getDepth()==0) - s= "bo:" + QString("%1").arg(getNum()); - else - s= ((BranchObj*)(parObj))->getSelectString() + ",bo:" + QString("%1").arg(getNum()); - } else - { - s="mc:"; - } - - return s; + return mapEditor->getModel()->getSelectString (this); } +void BranchObj::setAnimation(const AnimPoint &ap) +{ + anim=ap; +} + +bool BranchObj::animate() +{ + anim.animate (); + if ( anim.isAnimated() ) + { + setRelPos (anim); + return true; + } + return false; +} + diff -r e37153bea487 -r 394b2f297e1d tex/vym.changelog --- a/tex/vym.changelog Thu Jul 17 09:27:20 2008 +0000 +++ b/tex/vym.changelog Thu Jul 17 11:11:55 2008 +0000 @@ -1,6 +1,7 @@ ------------------------------------------------------------------- -Thu Jul 17 11:25:39 CEST 2008 - uwedr@suse.de +Thu Jul 17 13:11:39 CEST 2008 - uwedr@suse.de +- Bugfix: Deleting an animated part no longer segfaults - Bugfix: smaller image for export to elliminate pixel jitter on right side diff -r e37153bea487 -r 394b2f297e1d vymmodel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vymmodel.cpp Thu Jul 17 11:11:55 2008 +0000 @@ -0,0 +1,395 @@ +#include <QApplication> +#include <typeinfo> + +#include "geometry.h" // for addBBox +#include "vymmodel.h" + + +extern Settings settings; + +VymModel::VymModel() +{ +// cout << "Const VymModel\n"; +} + + +VymModel::~VymModel() +{ +// cout << "Destr VymModel\n"; +} + +void VymModel::clear() +{ + while (!mapCenters.isEmpty()) + delete mapCenters.takeFirst(); +} + +void VymModel::init () +{ + addMapCenter(); + + // animations + animationUse=settings.readBoolEntry("/animation/use",false); + animationTicks=settings.readNumEntry("/animation/ticks",10); + animationInterval=settings.readNumEntry("/animation/interval",50); + animObjList.clear(); + animationTimer=new QTimer (this); + connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate())); + +} + +void VymModel::setMapEditor(MapEditor *me) +{ + mapEditor=me; + for (int i=0; i<mapCenters.count(); i++) + mapCenters.at(i)->setMapEditor(mapEditor); +} + +MapEditor* VymModel::getMapEditor() +{ + return mapEditor; +} + +void VymModel::setVersion (const QString &s) +{ + version=s; +} + +void VymModel::setAuthor (const QString &s) +{ + author=s; +} + +QString VymModel::getAuthor() +{ + return author; +} + +void VymModel::setComment (const QString &s) +{ + comment=s; +} + +QString VymModel::getComment () +{ + return comment; +} + +QString VymModel::getDate () +{ + return QDate::currentDate().toString ("yyyy-MM-dd"); +} + +void VymModel::setScene (QGraphicsScene *s) +{ + mapScene=s; + init(); // Here we have a mapScene set, + // which is (still) needed to create MapCenters +} + +QGraphicsScene* VymModel::getScene () +{ + return mapScene; +} + +MapCenterObj* VymModel::addMapCenter() +{ + return addMapCenter (QPointF(0,0)); +} + +MapCenterObj* VymModel::addMapCenter(QPointF absPos) +{ + MapCenterObj *mapCenter = new MapCenterObj(mapScene); + mapCenter->move (absPos); + mapCenter->setVisibility (true); + mapCenter->setHeading (QApplication::translate("Heading of mapcenter in new map", "New map")); + mapCenter->setMapEditor(mapEditor); //FIXME needed to get defLinkStyle, mapLinkColorHint ... for later added objects + mapCenters.append(mapCenter); + return mapCenter; +} + +MapCenterObj *VymModel::removeMapCenter(MapCenterObj* mco) +{ + int i=mapCenters.indexOf (mco); + if (i>=0) + { + mapCenters.removeAt (i); + delete (mco); + if (i>0) return mapCenters.at(i-1); // Return previous MCO + } + return NULL; +} + +BranchObj* VymModel::first() +{ + if (mapCenters.count()>0) + return mapCenters.first(); + else + return NULL; +} + +BranchObj* VymModel::next(BranchObj *bo_start) +{ + BranchObj *rbo; + BranchObj *bo=bo_start; + if (bo) + { + // Try to find next branch in current MapCenter + rbo=bo->next(); + if (rbo) return rbo; + + // Try to find MapCenter of bo + while (bo->getDepth()>0) bo=(BranchObj*)bo->getParObj(); + + // Try to find next MapCenter + int i=mapCenters.indexOf ((MapCenterObj*)bo); + if (i+2 > mapCenters.count() || i<0) return NULL; + if (mapCenters.at(i+1)!=bo_start) + return mapCenters.at(i+1); + } + return NULL; +} + +LinkableMapObj* VymModel::findMapObj(QPointF p, LinkableMapObj *excludeLMO) +{ + LinkableMapObj *lmo; + + for (int i=0;i<mapCenters.count(); i++) + { + lmo=mapCenters.at(i)->findMapObj (p,excludeLMO); + if (lmo) return lmo; + } + return NULL; +} + +LinkableMapObj* VymModel::findObjBySelect(const QString &s) +{ + LinkableMapObj *lmo; + if (!s.isEmpty() ) + { + QString part; + QString typ; + QString num; + part=s.section(",",0,0); + typ=part.left (2); + num=part.right(part.length() - 3); + if (typ=="mc" && num.toInt()>=0 && num.toInt() <mapCenters.count() ) + return mapCenters.at(num.toInt() ); + } + + for (int i=0; i<mapCenters.count(); i++) + { + lmo=mapCenters.at(i)->findObjBySelect(s); + if (lmo) return lmo; + } + return NULL; +} + +LinkableMapObj* VymModel::findID (const QString &s) +{ + LinkableMapObj *lmo; + for (int i=0; i<mapCenters.count(); i++) + { + lmo=mapCenters.at(i)->findID (s); + if (lmo) return lmo; + } + return NULL; +} + +QString VymModel::saveToDir (const QString &tmpdir,const QString &prefix, int verbose, const QPointF &offset) +{ + QString s; + + for (int i=0; i<mapCenters.count(); i++) + s+=mapCenters.at(i)->saveToDir (tmpdir,prefix,verbose,offset); + return s; +} + + +////////////////////////////////////////////// +// View related +////////////////////////////////////////////// + +void VymModel::updateRelPositions() +{ + for (int i=0; i<mapCenters.count(); i++) + mapCenters.at(i)->updateRelPositions(); +} + +void VymModel::reposition() +{ + for (int i=0;i<mapCenters.count(); i++) + mapCenters.at(i)->reposition(); // for positioning heading +} + +QPolygonF VymModel::shape(BranchObj *bo) +{ + // Creating (arbitrary) shapes + + QPolygonF p; + QRectF rb=bo->getBBox(); + if (bo->getDepth()==0) + { + // Just take BBox of this mapCenter + p<<rb.topLeft()<<rb.topRight()<<rb.bottomRight()<<rb.bottomLeft(); + return p; + } + + // Take union of BBox and TotalBBox + + QRectF ra=bo->getTotalBBox(); + if (bo->getOrientation()==LinkableMapObj::LeftOfCenter) + p <<ra.bottomLeft() + <<ra.topLeft() + <<QPointF (rb.topLeft().x(), ra.topLeft().y() ) + <<rb.topRight() + <<rb.bottomRight() + <<QPointF (rb.bottomLeft().x(), ra.bottomLeft().y() ) ; + else + p <<ra.bottomRight() + <<ra.topRight() + <<QPointF (rb.topRight().x(), ra.topRight().y() ) + <<rb.topLeft() + <<rb.bottomLeft() + <<QPointF (rb.bottomRight().x(), ra.bottomRight().y() ) ; + return p; + +} + +void VymModel::moveAway(LinkableMapObj *lmo) +{ + // Autolayout: + // + // Move all branches and MapCenters away from lmo + // to avoid collisions + + QPolygonF pA; + QPolygonF pB; + + BranchObj *boA=(BranchObj*)lmo; + BranchObj *boB; + for (int i=0; i<mapCenters.count(); i++) + { + boB=mapCenters.at(i); + pA=shape (boA); + pB=shape (boB); + PolygonCollisionResult r = PolygonCollision(pA, pB, QPoint(0,0)); + cout <<"------->" + <<"="<<r.intersect + <<" ("<<qPrintable(boA->getHeading() )<<")" + <<" with ("<< qPrintable (boB->getHeading() ) + <<") willIntersect" + <<r.willIntersect + <<" minT="<<r.minTranslation<<endl<<endl; + } +} + +void VymModel::animate() +{ + animationTimer->stop(); + BranchObj *bo; + int i=0; + while (i<animObjList.size() ) + { + bo=(BranchObj*)animObjList.at(i); + if (!bo->animate()) + { + if (i>=0) animObjList.removeAt(i); + i--; + } + bo->reposition(); + i++; + } + mapEditor->updateSelection(); + mapScene->update(); + animationTimer->start(); +} + + +void VymModel::startAnimation(const QPointF &start, const QPointF &dest) +{ + BranchObj *bo=getSelectedBranch(); + if (bo && bo->getDepth()>0) + { + AnimPoint ap; + ap.setStart (start); + ap.setDest (dest); + ap.setTicks (animationTicks); + ap.setAnimated (true); + bo->setAnimation (ap); + animObjList.append( bo ); + animationTimer->setSingleShot (true); + animationTimer->start(animationInterval); + } +} + +void VymModel::stopAnimation(MapObj *mo) +{ + int i=animObjList.indexOf(mo); + if (i>=0) + animObjList.removeAt (i); +} + +////////////////////////////////////////////// +// Selection related +////////////////////////////////////////////// + + +// Only as long as we dont have Model/View yet +LinkableMapObj* VymModel::getSelection() +{ + return mapEditor->getSelection(); +} +BranchObj* VymModel::getSelectedBranch() +{ + return mapEditor->getSelectedBranch(); +} + + +bool VymModel::select (const QString &s) +{ + return mapEditor->select (s); +} + +QString VymModel::getSelectString (LinkableMapObj *lmo) +{ + QString s; + if (!lmo) return s; + if (typeid(*lmo)==typeid(BranchObj) || + typeid(*lmo)==typeid(MapCenterObj) ) + { + LinkableMapObj *par=lmo->getParObj(); + if (par) + { + if (lmo->getDepth() ==1) + // Mainbranch, return + s= "bo:" + QString("%1").arg(((BranchObj*)lmo)->getNum()); + else + // Branch, call myself recursively + s= getSelectString(par) + ",bo:" + QString("%1").arg(((BranchObj*)lmo)->getNum()); + } else + { + // MapCenter + int i=mapCenters.indexOf ((MapCenterObj*)lmo); + if (i>=0) s=QString("mc:%1").arg(i); + } + } + return s; + +} + + +void VymModel::setHideTmp (HideTmpMode mode) +{ + for (int i=0;i<mapCenters.count(); i++) + mapCenters.at(i)->setHideTmp (mode); +} + +QRectF VymModel::getTotalBBox() +{ + QRectF r; + for (int i=0;i<mapCenters.count(); i++) + r=addBBox (mapCenters.at(i)->getTotalBBox(), r); + return r; +} + diff -r e37153bea487 -r 394b2f297e1d vymmodel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vymmodel.h Thu Jul 17 11:11:55 2008 +0000 @@ -0,0 +1,86 @@ +#ifndef VYMMODEL_H +#define VYMMODEL_H + +#include <QGraphicsScene> + +#include "mapcenterobj.h" +#include "mapeditor.h" + + +/*! \brief This will later be divided into Model/View +*/ + +class VymModel : public QObject{ + Q_OBJECT + +public: + VymModel(); + ~VymModel (); + void clear(); + void init(); + void setMapEditor(MapEditor *me); // FIXME should not be necessary in Model/View + MapEditor* getMapEditor(); + void setVersion(const QString &); + void setAuthor (const QString &); + QString getAuthor (); + void setComment (const QString &); + QString getComment (); + QString getDate(); + void setScene(QGraphicsScene *s); + QGraphicsScene *getScene(); + MapCenterObj* addMapCenter(); + MapCenterObj* addMapCenter(QPointF absPos); + MapCenterObj* removeMapCenter(MapCenterObj *mco); + + BranchObj* first(); // FIXME replaced by ModelIndex later + BranchObj* next(BranchObj *bo); // FIXME replaced by ModelIndex later + + LinkableMapObj* findMapObj(QPointF,LinkableMapObj*); // find MapObj + LinkableMapObj* findObjBySelect (const QString &s); // find MapObj by select string + LinkableMapObj* findID (const QString &s); // find MapObj by previously set ID + QString saveToDir (const QString&,const QString&,int, const QPointF&);// Save data recursivly to tempdir + + +////////////////////////////////////////// View related + // void updateLink(); FIXME needed? + void updateRelPositions(); + + QRectF getTotalBBox(); + void reposition(); //!< Call reposition for all MCOs + void setHideTmp (HideTmpMode mode); + QPolygonF shape(BranchObj *bo); //!< Returns arbitrary shape of subtree + void moveAway (LinkableMapObj *lmo);//!< Autolayout: Move all out of the way + + // Animation **experimental** +private slots: + void animate(); //!< Called by timer to animate stuff +public: + void startAnimation (const QPointF &start, const QPointF &dest); + void stopAnimation (MapObj *mo); +private: + QTimer *animationTimer; + bool animationUse; + uint animationTicks; + uint animationInterval; + int timerId; // animation timer + QList <MapObj*> animObjList;// list with animated objects + +////////////////////////////////////////// Selection related +public: + LinkableMapObj* getSelection(); + BranchObj* getSelectedBranch(); + bool select (const QString &s); + QString getSelectString (LinkableMapObj *lmo); + +private: + QGraphicsScene *mapScene; + MapEditor *mapEditor; + QList <MapCenterObj*> mapCenters; + QString version; //!< version string saved in vym file + QString author; + QString comment; + QDate date; +}; + + +#endif