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