linkablemapobj.cpp
author insilmaril
Tue Jan 03 09:44:41 2006 +0000 (2006-01-03)
changeset 167 f7efd8c7c407
parent 164 d442a66e9121
child 175 728f51b71e71
permissions -rw-r--r--
1.7.6 New features for floatimages and fixes
     1 #include <math.h>
     2 
     3 #include "linkablemapobj.h"
     4 #include "branchobj.h"
     5 #include "mapeditor.h"
     6 
     7 #include "version.h"
     8 
     9 
    10 /////////////////////////////////////////////////////////////////
    11 // LinkableMapObj
    12 /////////////////////////////////////////////////////////////////
    13 
    14 LinkableMapObj::LinkableMapObj():MapObj()
    15 {
    16   //  cout << "Const LinkableMapObj ()\n";
    17     init ();
    18 }
    19 
    20 LinkableMapObj::LinkableMapObj(QCanvas* c) :MapObj(c)
    21 {
    22 //    cout << "Const LinkableMapObj\n";
    23     init ();
    24 }
    25 
    26 LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->canvas)
    27 {
    28     copy (lmo);
    29 }
    30 
    31 LinkableMapObj::~LinkableMapObj()
    32 {
    33     delete (bottomline);
    34     delete (selbox);
    35 	delete (frame);
    36 	delLink();
    37 }
    38 
    39 void LinkableMapObj::delLink()
    40 {
    41 	switch (style)
    42 	{
    43 		case StyleLine:
    44 			delete (l);
    45 			break;
    46 		case StyleParabel:
    47 			segment.clear();
    48 			break;
    49 		case StylePolyLine:
    50 			delete (p);
    51 			delete (l);
    52 			break;
    53 		case StylePolyParabel:
    54 			delete (p);
    55 			segment.clear();
    56 			break;
    57 		default:
    58 			break;
    59 	}		
    60 }
    61 
    62 void LinkableMapObj::init ()
    63 {
    64     depth=-1;	
    65 	mapEditor=NULL;
    66     childObj=NULL;
    67     parObj=NULL;
    68     parObjTmpBuf=NULL;
    69     parPos=QPoint(0,0);
    70     childPos=QPoint(0,0);
    71 	link2ParPos=false;
    72     l=NULL;
    73     orientation=OrientUndef;
    74     linkwidth=20;		
    75 	thickness_start=8;
    76     style=StyleUndef;
    77 	linkpos=LinkBottom;
    78     segment.setAutoDelete (TRUE);
    79     arcsegs=13;
    80 	QPointArray pa(arcsegs*2+2);
    81     
    82     bottomline=new QCanvasLine(canvas);
    83     bottomline->setPen( QPen(linkcolor, 1) );
    84     bottomline->setZ(Z_LINK);
    85     bottomline->show();
    86 
    87     // Prepare showing the selection of a MapObj
    88     selbox = new QCanvasRectangle (canvas);
    89     selbox->setZ(Z_SELBOX);
    90     selbox->setBrush( QColor(255,255,0) );
    91     selbox->setPen( QPen(QColor(255,255,0) ));
    92     selbox->hide();
    93     selected=false;
    94 
    95 	hideLinkUnselected=false;
    96 
    97 	// initialize frame
    98 	frame = new FrameObj (canvas);
    99 	
   100 	repositionRequest=false;
   101 }
   102 
   103 void LinkableMapObj::copy (LinkableMapObj* other)
   104 {
   105     MapObj::copy(other);
   106 	bboxTotal=other->bboxTotal;
   107     setLinkStyle(other->style);
   108     setLinkColor (other->linkcolor);
   109 }
   110 
   111 void LinkableMapObj::setChildObj(LinkableMapObj* o)
   112 {
   113     childObj=o;
   114 }
   115 
   116 void LinkableMapObj::setParObj(LinkableMapObj* o)
   117 {
   118     parObj=o;
   119 	mapEditor=parObj->getMapEditor();
   120 }
   121 
   122 void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
   123 {
   124 }
   125 
   126 void LinkableMapObj::unsetParObjTmp()
   127 {
   128 }
   129 
   130 bool LinkableMapObj::hasParObjTmp()
   131 {
   132 	if (parObjTmpBuf) return true;
   133 	return false;
   134 }
   135 
   136 LinkStyle LinkableMapObj::getDefLinkStyle ()
   137 {
   138 	if (!mapEditor) return StyleUndef;
   139 
   140 	LinkStyle ls=mapEditor->getLinkStyle();
   141 	switch (ls)
   142 	{
   143 		case StyleLine: 
   144 			return ls;
   145 			break;
   146 		case StyleParabel:
   147 			return ls;
   148 			break;
   149 		case StylePolyLine:	
   150 			if (depth>1)
   151 				return StyleLine;
   152 			else	
   153 				return ls;
   154 			break;
   155 		case StylePolyParabel:	
   156 			if (depth>1)
   157 				return StyleParabel;
   158 			else	
   159 				return ls;
   160 			break;
   161 		default: 
   162 			break;	
   163 	}	
   164 	return StyleUndef;
   165 }
   166 
   167 void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
   168 {
   169 	//if (newstyle=style) return;
   170 	delLink();
   171 		
   172 	style=newstyle;
   173 
   174     if (childObj!=NULL && parObj != NULL)
   175     {
   176 		int i;
   177 		QCanvasLine* cl;
   178 		switch (style)
   179 		{
   180 			case StyleUndef:
   181 				bottomline->hide();
   182 				break;
   183 			case StyleLine: 
   184 				l = new QCanvasLine(canvas);
   185 				l->setPen( QPen(linkcolor, 1) );
   186 				l->setZ(Z_LINK);
   187 				if (visible)
   188 					l->show();
   189 				else
   190 					l->hide();
   191 				break;
   192 			case StyleParabel:
   193 				for (i=0;i<arcsegs;i++)
   194 				{
   195 					cl = new QCanvasLine(canvas);
   196 					cl->setPen( QPen(linkcolor, 1) );
   197 					cl->setPoints( 0,0,i*10,100);
   198 					cl->setZ(Z_LINK);
   199 					if (visible)
   200 						cl->show();
   201 					else
   202 						cl->hide();
   203 					segment.append(cl);
   204 				}
   205 				pa0.resize (arcsegs+1);
   206 				break;
   207 			case StylePolyLine:	
   208 				p = new QCanvasPolygon(canvas);
   209 				p->setBrush( linkcolor );
   210 				p->setZ(Z_LINK);
   211 				if (visible)
   212 					p->show();
   213 				else
   214 					p->hide();
   215 				pa0.resize (3);
   216 				// TODO a bit awkward: draw the lines additionally to polygon, to avoid
   217 				// missing pixels, when polygon is extremly flat
   218 				l = new QCanvasLine(canvas);
   219 				l->setPen( QPen(linkcolor, 1) );
   220 				l->setZ(Z_LINK);
   221 				if (visible)
   222 					l->show();
   223 				else
   224 					l->hide();
   225 				break;
   226 			case StylePolyParabel:	
   227 				p = new QCanvasPolygon(canvas);
   228 				p->setBrush( linkcolor );
   229 				p->setZ(Z_LINK);
   230 				if (visible)
   231 					p->show();
   232 				else
   233 					p->hide();
   234 				pa0.resize (arcsegs*2+2);
   235 				pa1.resize (arcsegs+1);
   236 				pa2.resize (arcsegs+1);
   237 
   238 				// TODO a bit awkward: draw the lines additionally 
   239 				// to polygon, to avoid missing pixels, 
   240 				// if polygon is extremly flat
   241 				for (i=0;i<arcsegs;i++)
   242 				{
   243 					cl = new QCanvasLine(canvas);
   244 					cl->setPen( QPen(linkcolor, 1) );
   245 					cl->setPoints( 0,0,i*10,100);
   246 					cl->setZ(Z_LINK);
   247 					if (visible)
   248 						cl->show();
   249 					else
   250 						cl->hide();
   251 					segment.append(cl);
   252 				}
   253 				break;
   254 			default: 
   255 				break;	
   256 		}	
   257 	} 
   258 }
   259 
   260 LinkStyle LinkableMapObj::getLinkStyle()
   261 {
   262 	return style;
   263 }
   264 
   265 void LinkableMapObj::setHideLinkUnselected(bool b)
   266 {
   267 	hideLinkUnselected=b;
   268 	setVisibility (visible);
   269 	updateLink();
   270 }
   271 
   272 bool LinkableMapObj::getHideLinkUnselected()
   273 {
   274 	return hideLinkUnselected;
   275 }
   276 
   277 void LinkableMapObj::setLinkPos(LinkPos lp)
   278 {
   279 	linkpos=lp;
   280 }
   281 
   282 LinkPos LinkableMapObj::getLinkPos()
   283 {
   284 	return linkpos;
   285 }
   286 
   287 
   288 void LinkableMapObj::setLinkColor()
   289 {
   290 	// Overloaded in BranchObj and childs
   291 	// here only set default color
   292 	if (mapEditor)
   293 		setLinkColor (mapEditor->getDefLinkColor());
   294 }
   295 
   296 void LinkableMapObj::setLinkColor(QColor col)
   297 {
   298 	linkcolor=col;
   299     bottomline->setPen( QPen(linkcolor, 1) );
   300 	QCanvasLine *cl;
   301 	switch (style)
   302 	{
   303 		case StyleLine:
   304 			l->setPen( QPen(col,1));
   305 			break;	
   306 		case StyleParabel:	
   307 			for (cl=segment.first(); cl; cl=segment.next() )
   308 				cl->setPen( QPen(col,1));
   309 			break;
   310 		case StylePolyLine:
   311 			p->setBrush( QBrush(col));
   312 			l->setPen( QPen(col,1));
   313 			break;
   314 		case StylePolyParabel:	
   315 			p->setBrush( QBrush(col));
   316 			for (cl=segment.first(); cl; cl=segment.next() )
   317 				cl->setPen( QPen(col,1));
   318 			break;
   319 		default:
   320 			break;
   321 	} // switch (style)	
   322 }
   323 
   324 QColor LinkableMapObj::getLinkColor()
   325 {
   326 	return linkcolor;
   327 }
   328 
   329 FrameType LinkableMapObj::getFrameType()
   330 {
   331 	return frame->getFrameType();
   332 }
   333 
   334 void LinkableMapObj::setFrameType(const FrameType &t)
   335 {
   336 	frame->setFrameType(t);
   337 	calcBBoxSize();
   338 	positionBBox();
   339 	requestReposition();
   340 }
   341 
   342 void LinkableMapObj::setFrameType(const QString &t)
   343 {
   344 	frame->setFrameType(t);
   345 	calcBBoxSize();
   346 	positionBBox();
   347 	requestReposition();
   348 }
   349 
   350 void LinkableMapObj::setVisibility (bool v)
   351 {
   352 	QCanvasLine* cl;
   353 	MapObj::setVisibility (v);
   354 	bool visnow=visible;
   355 	if (hideLinkUnselected && !selected)
   356 		visnow=false;
   357 
   358 	if (visnow) 
   359 	{
   360 		bottomline->show();
   361 		switch (style)
   362 		{
   363 			case StyleLine:
   364 				if (l) l->show();
   365 				break;
   366 			case StyleParabel:	
   367 				for (cl=segment.first(); cl; cl=segment.next() )
   368 					cl->show();
   369 				break;	
   370 			case StylePolyLine:
   371 				if (p) p->show();
   372 				if (l) l->show();
   373 				break;
   374 			case StylePolyParabel:	
   375 				for (cl=segment.first(); cl; cl=segment.next() )
   376 					cl->show();
   377 				if (p) p->show();
   378 				break;
   379 			default:
   380 				break;
   381 		}
   382 	} else 
   383 	{
   384 		bottomline->hide();
   385 		switch (style)
   386 		{
   387 			case StyleLine:
   388 				if (l) l->hide();
   389 				break;
   390 			case StyleParabel:	
   391 				for (cl=segment.first(); cl; cl=segment.next() )
   392 					cl->hide();
   393 				break;	
   394 			case StylePolyLine:
   395 				if (p) p->hide();
   396 				if (l) l->hide();
   397 				break;
   398 			case StylePolyParabel:	
   399 				for (cl=segment.first(); cl; cl=segment.next() )
   400 					cl->hide();
   401 				if (p) p->hide();
   402 				break;
   403 			default:
   404 				break;
   405 		}
   406 	}	
   407 }
   408 
   409 void LinkableMapObj::updateLink()
   410 {
   411     // needs:
   412     //	childPos of parent
   413     //	orient   of parent
   414     //	style
   415     // 
   416     // sets:
   417     //	orientation
   418     //	childPos
   419     //	parPos
   420 	//  offset
   421     //	drawing of the link itself
   422 
   423 
   424 	// updateLink is called from move, but called from constructor we don't
   425 	// have parents yet...
   426 	if (style==StyleUndef) return;	
   427 
   428 	if (frame->getFrameType() == NoFrame)
   429 		linkpos=LinkBottom;
   430 	else	
   431 		linkpos=LinkMiddle;
   432 	switch (linkpos)
   433 	{
   434 		case LinkMiddle:
   435 			offset=bbox.height() /2;
   436 			break;
   437 		default :
   438 			offset=bbox.height()-1;			// draw link to bottom of bbox
   439 			break;
   440 	}
   441 	
   442     double p2x,p2y;								// Set P2 Before setting
   443 	if (!link2ParPos)
   444 	{
   445 		p2x=QPoint( parObj->getChildPos() ).x();	// P1, we have to look at
   446 		p2y=QPoint( parObj->getChildPos() ).y();	// orientation
   447 	} else	
   448 	{
   449 		p2x=QPoint( parObj->getParPos() ).x();	
   450 		p2y=QPoint( parObj->getParPos() ).y();
   451 	} 
   452 
   453 	LinkOrient orientOld=orientation;
   454 
   455     // Set orientation, first look for orientation of parent
   456     if (parObj->getOrientation() != OrientUndef ) 
   457 		// use the orientation of the parent:
   458 		orientation=parObj->getOrientation();
   459     else
   460     {
   461 		// calc orientation depending on position rel to mapCenter
   462 		if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
   463 			orientation=OrientLeftOfCenter; 
   464 		else
   465 			orientation=OrientRightOfCenter;
   466     }
   467 
   468 	if ((orientation!=orientOld) && (orientOld!= OrientUndef))
   469 	{
   470 		// Orientation just changed. Reorient this subbranch, because move is called
   471 		// before updateLink => Position is still the old one, which could lead to 
   472 		// linking of subranch to itself => segfault
   473 		//
   474 		// Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
   475 		// no need to reposition now
   476 		reposition();
   477 	}
   478 	
   479     if (orientation==OrientLeftOfCenter )
   480     {
   481 		childPos=QPoint (absPos.x(),absPos.y()+offset);
   482 		parPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset );
   483     } else
   484     {
   485 		childPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset ); 
   486 		parPos=QPoint (absPos.x(),absPos.y()+offset);
   487     }
   488 
   489 	double p1x=parPos.x();	// Link is drawn from P1 to P2
   490 	double p1y=parPos.y();
   491 
   492 	double vx=p2x - p1x;	// V=P2-P1
   493 	double vy=p2y - p1y;
   494 
   495 	// Draw the horizontal line below heading (from ChildPos to ParPos)
   496 	bottomline->setPoints (qRound(childPos.x()),
   497 		qRound(childPos.y()),
   498 		qRound(p1x),
   499 		qRound(p1y) );
   500 
   501 	double a;	// angle
   502 	if (vx > -0.000001 && vx < 0.000001)
   503 		a=M_PI_2;
   504 	else
   505 		a=atan( vy / vx );
   506 	// "turning point" for drawing polygonal links
   507 	QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));	
   508 	
   509 	QCanvasLine *cl;
   510 
   511 	int i;
   512 
   513     // Draw the link
   514 	switch (style)
   515 	{
   516 		case StyleLine:
   517 			l->setPoints( qRound (parPos.x()),
   518 				qRound(parPos.y()),
   519 				qRound(p2x),
   520 				qRound(p2y) );
   521 			break;	
   522 		case StyleParabel:	
   523 			parabel (pa0, p1x,p1y,p2x,p2y);
   524 			i=0;
   525 			for (cl=segment.first(); cl; cl=segment.next() )
   526 			{	
   527 				cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
   528 				i++;
   529 			}
   530 			break;
   531 		case StylePolyLine:
   532 			pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
   533 			pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
   534 			pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
   535 			p->setPoints (pa0);
   536 			// here too, draw line to avoid missing pixels
   537 			l->setPoints( qRound (parPos.x()),
   538 				qRound(parPos.y()),
   539 				qRound(p2x),
   540 				qRound(p2y) );
   541 			break;
   542 		case StylePolyParabel:	
   543 			parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
   544 			parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
   545 			for (i=0;i<=arcsegs;i++)
   546 			{
   547 				// Combine the arrays to a single one
   548 				pa0[i]=pa1[i];
   549 				pa0[i+arcsegs+1]=pa2[arcsegs-i];
   550 			}	
   551 			p->setPoints (pa0);
   552 			i=0;
   553 			for (cl=segment.first(); cl; cl=segment.next() )
   554 			{	
   555 				cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
   556 				i++;
   557 			}
   558 			break;
   559 		default:
   560 			break;
   561 	} // switch (style)	
   562 }
   563 	
   564 LinkableMapObj* LinkableMapObj::getChildObj()
   565 {
   566     return childObj;
   567 }
   568 
   569 LinkableMapObj* LinkableMapObj::getParObj()
   570 {
   571     return parObj;
   572 }
   573 
   574 LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
   575 {
   576 	LinkableMapObj *lmo=this;
   577 	QString part;
   578 	QString typ;
   579 	QString num;
   580 	while (!s.isEmpty() )
   581 	{
   582 		part=s.section(",",0,0);
   583 		typ=part.left (3);
   584 		num=part.right(part.length() - 3);
   585 		if (typ=="mc:")
   586 		{
   587 			if (depth>0)
   588 				return false;	// in a subtree there is no center
   589 			else
   590 				break;
   591 		} else
   592 			if (typ=="bo:")
   593 				lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
   594 			else
   595 				if (typ=="fi:")
   596 					lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
   597 		if (!lmo) break;
   598 		
   599 		if (s.contains(","))
   600 			s=s.right(s.length() - part.length() -1 );
   601 		else	
   602 			break;
   603 	}
   604 	return lmo;
   605 }
   606 
   607 QPoint LinkableMapObj::getChildPos()
   608 {
   609     return childPos;
   610 }
   611 
   612 QPoint LinkableMapObj::getParPos()
   613 {
   614     return parPos;
   615 }
   616 
   617 QPoint LinkableMapObj::getRelPos()
   618 {
   619 	if (!parObj) return QPoint (0,0);
   620     return QPoint(
   621 		absPos.x() - parObj->x(),
   622 		absPos.y() - parObj->y()
   623 	);
   624 }
   625 
   626 LinkOrient LinkableMapObj::getOrientation()
   627 {
   628     return orientation;
   629 }
   630 
   631 int LinkableMapObj::getDepth()
   632 {
   633     return depth;
   634 }
   635 
   636 void LinkableMapObj::setMapEditor (MapEditor *me)
   637 {
   638 	mapEditor=me;
   639 }
   640 
   641 MapEditor* LinkableMapObj::getMapEditor ()
   642 {
   643 	return mapEditor;
   644 }
   645 
   646 QPoint LinkableMapObj::getRandPos()
   647 {
   648 	// Choose a random position with given distance to parent:
   649 	double a=rand()%360 * 2 * M_PI / 360;
   650     return QPoint ( (int)( + 150*cos (a)),
   651                     (int)( + 150*sin (a)));
   652 }
   653 
   654 void LinkableMapObj::alignRelativeTo (QPoint ref)
   655 {
   656 	// FIXME testing, seems not to be used right now...
   657 	cout << "LMO::alignRelTo   ref="<<ref<<endl;
   658 }
   659 
   660 void LinkableMapObj::reposition()
   661 {
   662 	if (depth==0)
   663 	{
   664 		// only calculate the sizes once. If the deepest LMO changes its height,
   665 		// all upper LMOs have to change, too.
   666 		calcBBoxSizeWithChilds();
   667 
   668 	    alignRelativeTo ( QPoint (absPos.x(),
   669 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   670 	} else
   671 	{
   672 		// This is only important for moving branches:
   673 		// For editing a branch it isn't called...
   674 	    alignRelativeTo ( QPoint (absPos.x(),
   675 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   676 	}
   677 }
   678 
   679 void LinkableMapObj::requestReposition()
   680 {
   681 	if (!repositionRequest)
   682 	{
   683 		// Pass on the request to parental objects, if this hasn't
   684 		// been done yet
   685 		repositionRequest=true;
   686 		if (parObj) parObj->requestReposition();
   687 	}
   688 }
   689 
   690 void LinkableMapObj::forceReposition()
   691 {
   692 	// Sometimes a reposition has to be done immediatly: For example
   693 	// if the note editor flag changes, there is no user event in mapeditor
   694 	// which could collect requests for a reposition.
   695 	// Then we have to call forceReposition()
   696 	// But no rule without exception: While loading a map or undoing it,
   697 	// we want to block expensive repositioning, but just do it once at
   698 	// the end, thus check first:
   699 
   700 	if (mapEditor->isRepositionBlocked()) return;
   701 	
   702 	// Pass on the request to parental objects, if this hasn't been done yet
   703 	
   704 	if (parObj) 
   705 		parObj->forceReposition(); 
   706 	else 
   707 		reposition(); 
   708 }
   709 
   710 bool LinkableMapObj::repositionRequested()
   711 {
   712 	return repositionRequest;
   713 }
   714 
   715 
   716 void LinkableMapObj::setSelBox()
   717 {
   718     selbox->setX (bbox.x() );
   719     selbox->setY (bbox.y() );
   720     selbox->setSize (bbox.width(), bbox.height() );
   721 }
   722 
   723 void LinkableMapObj::select()
   724 {
   725 	setSelBox();
   726     selected=true;
   727     selbox->show();
   728 	setVisibility (visible);
   729 }
   730 
   731 
   732 void LinkableMapObj::unselect()
   733 {
   734     selected=false;
   735     selbox->hide();
   736 	setVisibility (visible);
   737 }
   738 
   739 void LinkableMapObj::parabel (QPointArray &ya, double p1x, double p1y, double p2x, double p2y)
   740 
   741 {
   742 	double vx=p2x - p1x;	// V=P2-P1
   743 	double vy=p2y - p1y;
   744 
   745 	double dx;				// delta x during calculation of parabel
   746 	
   747 	double pnx;				// next point
   748 	double pny;
   749 	double m;
   750 
   751 	if (vx > -0.0001 && vx < 0.0001)
   752 		m=0;
   753 	else	
   754 		m=(vy / (vx*vx));
   755 	dx=vx/(arcsegs);
   756 	int i;
   757 	ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
   758 	for (i=1;i<=arcsegs;i++)
   759 	{	
   760 		pnx=p1x+dx;
   761 		pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
   762 		ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
   763 		p1x=pnx;
   764 		p1y=pny;
   765 	}	
   766 }
   767 
   768 QString LinkableMapObj::getLinkAttr ()
   769 {
   770 	QString hideAttr;
   771 	if (hideLinkUnselected)
   772 		// Since this is currently the
   773 		// only attribut and it is switched off by default
   774 		// don't write <link>  at all if it is missing
   775 		return attribut ("hideLinkUnselected","true");
   776 	else
   777 		return "";
   778 	
   779 }