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