branchitem.cpp
author insilmaril
Wed, 10 Feb 2010 13:48:42 +0000
changeset 822 c2ce9944148c
parent 819 8f987e376035
child 823 0bba81dde1bc
permissions -rw-r--r--
More fixes and sorting lexically backwards
     1 #include "attributeitem.h"
     2 #include "branchitem.h"
     3 #include "branchobj.h"
     4 #include "vymmodel.h"
     5 #include "xlinkitem.h"
     6 
     7 #include <iostream>
     8 #include <QDir>
     9 
    10 using namespace std;
    11 
    12 BranchItem::BranchItem(const QList<QVariant> &data, TreeItem *parent):MapItem (data,parent)
    13 {
    14 	//cout << "Constr. BranchItem\n";
    15 
    16 	// Set type if parent is known yet 
    17 	// if not, type is set in insertBranch or TreeItem::appendChild
    18 	if (parent==rootItem)
    19 		setType (MapCenter);
    20 	else
    21 		setType (Branch);
    22 
    23 	scrolled=false;
    24 	tmpUnscrolled=false;
    25 
    26 	includeImagesVer=false;
    27 	includeImagesHor=false;
    28 	 
    29 	lastSelectedBranchNum=-1;
    30 	lastSelectedBranchNumAlt=-1;
    31 }
    32 
    33 BranchItem::~BranchItem()
    34 {
    35 	//cout << "Destr. BranchItem "<<getHeadingStd()<<endl;
    36 	if (lmo) 
    37 	{
    38 		delete lmo;
    39 		lmo=NULL;
    40 	}
    41 }
    42 
    43 void BranchItem::copy (BranchItem *other)
    44 {
    45 	scrolled=other->scrolled;
    46 	tmpUnscrolled=other->tmpUnscrolled;
    47 }
    48 
    49 BranchItem* BranchItem::parentBranch ()
    50 {
    51 	return (BranchItem*) parentItem;
    52 }
    53 
    54 void BranchItem::insertBranch (int pos, BranchItem *branch)
    55 {
    56 	if (pos<0) pos=0;
    57 	if (pos>branchCounter) pos=branchCounter;
    58     childItems.insert(pos+branchOffset,branch);
    59 	branch->parentItem=this;
    60 	branch->rootItem=rootItem;
    61 	branch->setModel (model);
    62 	if (parentItem==rootItem)
    63 		setType (MapCenter);
    64 	else
    65 		setType (Branch);
    66 
    67 
    68 	if (branchCounter==0)
    69 		branchOffset=childItems.count()-1;
    70 	branchCounter++;
    71 }
    72 
    73 QString BranchItem::saveToDir (const QString &tmpdir,const QString &prefix, const QPointF& offset) //FIXME-3 Check if everything is saved...
    74 {
    75 	// Cloudy stuff can be hidden during exports
    76 	if (hidden) return QString();
    77 
    78     QString s,a;
    79 	BranchObj *bo=(BranchObj*)lmo;
    80 
    81 	// Update of note is usually done while unselecting a branch
    82 	
    83 	QString scrolledAttr;
    84 	if (scrolled) 
    85 		scrolledAttr=attribut ("scrolled","yes");
    86 	else
    87 		scrolledAttr="";
    88 
    89 	// save area, if not scrolled	// FIXME-5 not needed if HTML is rewritten...
    90 									// also we should check if _any_ of parents is scrolled
    91 	QString areaAttr;
    92 	if (lmo && parentItem->isBranchLikeType() && !((BranchItem*)parentItem)->isScrolled() )
    93 	{
    94 		qreal x=lmo->getAbsPos().x();
    95 		qreal y=lmo->getAbsPos().y();
    96 		areaAttr=
    97 			attribut("x1",QString().setNum(x-offset.x())) +
    98 			attribut("y1",QString().setNum(y-offset.y())) +
    99 			attribut("x2",QString().setNum(x+lmo->width()-offset.x())) +
   100 			attribut("y2",QString().setNum(y+lmo->height()-offset.y()));
   101 
   102 	} else
   103 		areaAttr="";
   104 	
   105 	// Provide an ID for a branch makes export to XHTML easier
   106 	QString idAttr;
   107 	if (xlinkCount()>0)
   108 		idAttr=attribut ("id",model->getSelectString(this)); 
   109 	else
   110 		idAttr="";
   111 
   112 	QString elementName;
   113 	if (parentItem==rootItem)
   114 		elementName="mapcenter";
   115 	else	
   116 		elementName="branch";
   117 
   118     s=beginElement (elementName
   119 		+getMapAttr()
   120 		+getGeneralAttr()
   121 		+scrolledAttr 
   122 	//	+areaAttr	// FIXME-4 not needed anymore. Wait until end of 2010 before removing...
   123 		+idAttr 
   124 		+getIncludeImageAttr() 
   125 		);
   126     incIndent();
   127 
   128 	// save heading
   129     s+=valueElement("heading", getHeading(),
   130 		attribut ("textColor",QColor( bo->getColor()).name()));
   131 
   132 	// Save frame  //FIXME-4 not saved if there is no LMO
   133 	if (lmo && ((OrnamentedObj*)lmo)->getFrame()->getFrameType()!=FrameObj::NoFrame) 
   134 		s+=((OrnamentedObj*)lmo)->getFrame()->saveToDir ();
   135 
   136 	// save names of flags set
   137 	s+=standardFlags.saveToDir(tmpdir,prefix,0);
   138 	
   139 	// Save Images
   140 	for (int i=0; i<imageCount(); ++i)
   141 		s+=getImageNum(i)->saveToDir (tmpdir,prefix);
   142 
   143 	// save note
   144 	if (!note.isEmpty() )
   145 		s+=note.saveToDir();
   146 	
   147 	// Save branches
   148 	int i=0;
   149 	TreeItem *ti=getBranchNum(i);
   150 	while (ti)
   151 	{
   152 		s+=getBranchNum(i)->saveToDir(tmpdir,prefix,offset);
   153 		i++;
   154 		ti=getBranchNum(i);
   155 	}	
   156 
   157 	// Save XLinks 
   158 	QString ol;	// old link
   159 	QString cl;	// current link
   160 	for (int i=0; i<xlinkCount(); ++i)
   161 	{
   162 		cl=getXLinkNum(i)->saveToDir();
   163 		if (cl!=ol)
   164 		{
   165 			s+=cl;
   166 			ol=cl;
   167 		} else
   168 		{
   169 			qWarning (QString("Ignoring of duplicate xLink in %1").arg(getHeading()));
   170 		}
   171 	}	
   172 
   173     decIndent();
   174     s+=endElement   (elementName);
   175     return s;
   176 }
   177 
   178 void BranchItem::updateVisibility()	
   179 {
   180 	// Needed to hide relinked branch, if parent is scrolled
   181 	if (lmo)
   182 	{
   183 		if (hasScrolledParent(this) || hidden)
   184 			lmo->setVisibility (false);
   185 		else	
   186 			lmo->setVisibility (true);
   187 	}
   188 }
   189 
   190 void BranchItem::setHeadingColor (QColor color)
   191 {
   192 	TreeItem::setHeadingColor (color);
   193 	if (lmo) ((BranchObj*)lmo)->setColor (color);
   194 }
   195 
   196 void BranchItem::unScroll()
   197 {
   198 	if (tmpUnscrolled) resetTmpUnscroll();
   199 	if (scrolled) toggleScroll();
   200 }
   201 
   202 bool BranchItem::toggleScroll()	
   203 {
   204 	BranchObj *bo=NULL;
   205 	if (scrolled)
   206 	{
   207 		scrolled=false;
   208 		systemFlags.deactivate("system-scrolledright");
   209 		if (branchCounter>0)
   210 		{
   211 			for (int i=0;i<branchCounter;++i)
   212 			{
   213 				bo=(BranchObj*)(getBranchNum(i)->getLMO());
   214 				if (bo) bo->setVisibility(true);
   215 			}
   216 		}
   217 	} else
   218 	{
   219 		scrolled=true;
   220 		systemFlags.activate("system-scrolledright");
   221 		if (branchCounter>0)
   222 		{
   223 			for (int i=0;i<branchCounter;++i)
   224 			{
   225 				bo=(BranchObj*)(getBranchNum(i)->getLMO());
   226 				if (bo) bo->setVisibility(false);
   227 			}
   228 		}
   229 	}
   230 	//model->reposition();	// FIXME-3 we don't really want to update view from here...
   231 	return true;
   232 }
   233 
   234 bool BranchItem::isScrolled()
   235 {
   236 	return scrolled;
   237 }
   238 
   239 bool BranchItem::hasScrolledParent(BranchItem *start)
   240 {
   241 	// Calls parents recursivly to
   242 	// find out, if we are scrolled at all.
   243 	// But ignore myself, just look at parents.
   244 
   245 	if (this !=start && scrolled) return true;
   246 
   247 	BranchItem* bi=(BranchItem*)parentItem;
   248 	if (bi && bi!=rootItem ) 
   249 		return bi->hasScrolledParent(start);
   250 	else
   251 		return false;
   252 }
   253 
   254 bool BranchItem::tmpUnscroll()
   255 {
   256 	bool result=false;
   257 
   258 	// Unscroll parent (recursivly)
   259 	BranchItem * pi=(BranchItem*)parentItem;
   260 	if (pi && pi->isBranchLikeType() ) result=pi->tmpUnscroll();
   261 		
   262 	// Unscroll myself
   263 	if (scrolled)
   264 	{
   265 		tmpUnscrolled=true;
   266 		systemFlags.activate("system-tmpUnscrolledRight");
   267 		toggleScroll();
   268 		model->emitDataHasChanged (this);
   269 		result=true;
   270 	}	
   271 	return result;
   272 }
   273 
   274 bool BranchItem::resetTmpUnscroll()
   275 {
   276 	bool result=false;
   277 
   278 	// Unscroll parent (recursivly)
   279 	BranchItem * pi=(BranchItem*)parentItem;
   280 	if (pi && pi->isBranchLikeType() ) result=pi->resetTmpUnscroll();
   281 		
   282 	// Unscroll myself
   283 	if (tmpUnscrolled)
   284 	{
   285 		tmpUnscrolled=false;
   286 		systemFlags.deactivate("system-tmpUnscrolledRight");
   287 		toggleScroll();
   288 		model->emitDataHasChanged (this);
   289 		result=true;
   290 	}	
   291 	return result;
   292 }
   293 
   294 void BranchItem::sortChildren(bool inverse)
   295 {
   296 	int childCount=branchCounter; 
   297 	int curChildIndex;
   298 	bool madeChanges=false;
   299 	do
   300 	{
   301 		madeChanges=false;
   302 		if (inverse)
   303 			for(curChildIndex=1;curChildIndex<childCount;curChildIndex++)
   304 			{
   305 				BranchItem* curChild =getBranchNum(curChildIndex);
   306 				BranchItem* prevChild=getBranchNum(curChildIndex-1);
   307 				if (prevChild->getHeading().compare(curChild->getHeading())<0)
   308 				{
   309 					model->moveUp (curChild);
   310 					madeChanges=true;
   311 				}	
   312 			} 
   313 		else
   314 			for(curChildIndex=1;curChildIndex<childCount;curChildIndex++)
   315 			{
   316 				BranchItem* curChild =getBranchNum(curChildIndex);
   317 				BranchItem* prevChild=getBranchNum(curChildIndex-1);
   318 				if ( prevChild->getHeading().compare(curChild->getHeading())>0)
   319 				{
   320 					model->moveUp(curChild);
   321 					madeChanges=true;
   322 				}	
   323 			}
   324 	}while(madeChanges);
   325 }
   326 
   327 void BranchItem::setIncludeImagesVer(bool b)
   328 {
   329 	includeImagesVer=b;
   330 	/* calcBBoxSize(); FIXME-3
   331 	positionBBox();
   332 	requestReposition();
   333 	*/
   334 }
   335 
   336 bool BranchItem::getIncludeImagesVer()
   337 {
   338 	return includeImagesVer;
   339 }
   340 
   341 void BranchItem::setIncludeImagesHor(bool b)
   342 {
   343 	includeImagesHor=b;
   344 	/* calcBBoxSize(); FIXME-3
   345 	positionBBox();
   346 	requestReposition();
   347 	*/
   348 }
   349 
   350 bool BranchItem::getIncludeImagesHor()
   351 {
   352 	return includeImagesHor;
   353 }
   354 
   355 QString BranchItem::getIncludeImageAttr()
   356 {
   357 	QString a;
   358 	if (includeImagesVer)
   359 		a=attribut ("incImgV","true");
   360 	if (includeImagesHor)
   361 		a+=attribut ("incImgH","true");
   362 	return a;	
   363 }
   364 
   365 void BranchItem::setLastSelectedBranch()
   366 {
   367 	int d=depth();
   368 	if (d>=0)
   369 	{
   370 		if (d==1)
   371 			// Hack to save an additional lastSelected for mapcenters in MapEditor
   372 			// depending on orientation
   373 			// this allows to go both left and right from there
   374 			if (lmo && lmo->getOrientation()==LinkableMapObj::LeftOfCenter)
   375 			{
   376 				((BranchItem*)parentItem)->lastSelectedBranchNumAlt=parentItem->num(this);
   377 				return;
   378 			}
   379 		((BranchItem*)parentItem)->lastSelectedBranchNum=parentItem->num(this);
   380 	}
   381 }
   382 
   383 void BranchItem::setLastSelectedBranch(int i)
   384 {
   385 		lastSelectedBranchNum=i;
   386 }
   387 
   388 BranchItem* BranchItem::getLastSelectedBranch()
   389 {
   390 	if (lastSelectedBranchNum>=branchCounter)
   391 		return getBranchNum (branchCounter-1);
   392 	else	
   393 		return getBranchNum (lastSelectedBranchNum);
   394 }
   395 
   396 BranchItem* BranchItem::getLastSelectedBranchAlt()
   397 {
   398 	return getBranchNum (lastSelectedBranchNumAlt);
   399 }
   400 
   401 
   402 
   403 
   404 TreeItem* BranchItem::findMapItem (QPointF p, TreeItem* excludeTI)
   405 {
   406 	// Search branches
   407 	TreeItem *ti;
   408 	for (int i=0; i<branchCount(); ++i)
   409     {	
   410 		ti=getBranchNum(i)->findMapItem(p, excludeTI);
   411 		if (ti != NULL) return ti;
   412     }
   413 	
   414 
   415 	// Search myself
   416     if (getBranchObj()->isInClickBox (p) && (this != excludeTI) && getBranchObj()->isVisibleObj() ) 
   417 		return this;
   418 
   419 	// Search images
   420 	ImageItem *ii;
   421     for (int i=0; i<imageCount(); ++i )
   422 	{
   423 		ii=getImageNum (i);
   424 		LinkableMapObj *mo=ii->getLMO();
   425 		if (mo && mo->isInClickBox(p) && 
   426 			(ii != excludeTI) && 
   427 			this!= excludeTI &&
   428 			mo->isVisibleObj() 
   429 		) return ii;
   430 	}
   431 
   432 	// Search attributes
   433 	AttributeItem *ai;
   434     for (int i=0; i<attributeCount(); ++i )
   435 	{
   436 		ai=getAttributeNum (i);
   437 		LinkableMapObj *mo=ai->getLMO();
   438 		if (mo && mo->isInClickBox(p) && 
   439 			(ii != excludeTI) && 
   440 			this!= excludeTI &&
   441 			mo->isVisibleObj() 
   442 		) return ai;
   443 	}
   444 
   445 	return NULL;
   446 }
   447 
   448 void BranchItem::updateStyles(const bool &keepFrame)
   449 {
   450 	// FIXME-5 compare also MapItem::initLMO...
   451 
   452 	if (lmo)
   453 	{ 
   454 		if ( parentItem != rootItem)
   455 			lmo->setParObj ( ((MapItem*)parentItem)->getLMO() );
   456 		else
   457 			lmo->setParObj (NULL);
   458 		((BranchObj*)lmo)->setDefAttr(BranchObj::MovedBranch,keepFrame);
   459 	}
   460 }
   461 
   462 BranchObj* BranchItem::getBranchObj()	// FIXME-3 only for transition BO->BI
   463 {
   464 	return (BranchObj*)lmo;
   465 }
   466 
   467 BranchObj* BranchItem::createMapObj(QGraphicsScene *scene)	// FIXME-4 maybe move this into MapEditor to get rid of scene in VymModel?
   468 {
   469 	BranchObj *newbo;
   470 	newbo=new BranchObj(scene,this);
   471 	lmo=newbo;
   472 
   473 	if (parentItem==rootItem)
   474 	{
   475 		newbo->setParObj(NULL);
   476 		//newbo->setFrameType (FrameObj::Rectangle);	//FIXME-4 maybe call updateStyles?
   477 	} else
   478 	{
   479 		newbo->setParObj( ((MapItem*)parentItem)->getLMO() );
   480 		// Set visibility depending on parents
   481 		if (parentItem!=rootItem && 
   482 			( ((BranchItem*)parentItem)->scrolled || !((MapItem*)parentItem)->getLMO()->isVisibleObj() ) )
   483 			newbo->setVisibility (false);
   484 	}
   485 	newbo->setDefAttr(BranchObj::NewBranch);
   486 	initLMO();
   487 
   488 	if (!getHeading().isEmpty() ) 
   489 	{
   490 		newbo->updateData();	//FIXME-3 maybe better model->emitDataHasChanged()?
   491 		newbo->setColor (headingColor);
   492 	}	
   493 		
   494 	//newbo->updateLinkGeometry();	//FIXME-3
   495 
   496 	return newbo;
   497 }
   498