File indexing completed on 2023-10-01 04:14:07
0001 /*************************************************************************** 0002 cmappath.cpp 0003 ------------------- 0004 begin : Sat Mar 10 2001 0005 copyright : (C) 2001 by Kmud Developer Team 0006 email : kmud-devel@kmud.de 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 ***************************************************************************/ 0017 0018 #include "cmappath.h" 0019 0020 #include "cmapmanager.h" 0021 0022 #include <kdebug.h> 0023 #include <klocale.h> 0024 #include <kconfiggroup.h> 0025 0026 #include <qregion.h> 0027 #include <QPolygon> 0028 0029 #include <math.h> 0030 #include <stdlib.h> 0031 0032 #include "cmaplevel.h" 0033 #include "cmapcmdelementproperties.h" 0034 0035 CMapPath::CMapPath(CMapManager *manager,CMapRoom *srcRoom,directionTyp srcDir,CMapRoom *destRoom,directionTyp destDir, bool twoWay) : CMapElement(manager,nullptr) 0036 { 0037 setSrcRoom(srcRoom); 0038 setDestRoom(destRoom); 0039 setSrcDir(srcDir); 0040 setDestDir(destDir); 0041 setCords(); 0042 bSpecialExit = false; 0043 specialCmd = ""; 0044 0045 setLevel(srcRoom->getLevel()); 0046 srcRoom->addPath(this); 0047 destRoom->getConnectingPathList()->append(this); 0048 0049 // Check to see if there is a a path in the opsite directon, if so make this a two way path 0050 bool found = false; 0051 foreach (CMapPath *path, *destRoom->getPathList()) 0052 { 0053 // FIXME_jp : Fix this for multiple special paths between the same rooms with different cmd's 0054 if (path->getDestRoom()==srcRoom && 0055 path->getSrcDir() == destDir && 0056 path->getDestDir() == srcDir && 0057 path->getSpecialCmd() == "") 0058 { 0059 setOpsitePath(path); 0060 path->setOpsitePath(this); 0061 found = true; 0062 } 0063 } 0064 if (twoWay && (!found)) makeTwoWay(); 0065 0066 beforeCommand = ""; 0067 afterCommand = ""; 0068 done = false; 0069 opsitePath = nullptr; 0070 0071 m_dontPaintBend=0; 0072 } 0073 0074 CMapPath::CMapPath(CMapManager *manager,CMapRoom *srcRoom,CMapRoom *destRoom) : CMapElement(manager,nullptr) 0075 { 0076 setSrcRoom(srcRoom); 0077 setDestRoom(destRoom); 0078 setSrcDir(NORTH); 0079 setDestDir(SOUTH); 0080 0081 beforeCommand = ""; 0082 afterCommand = ""; 0083 bSpecialExit = false; 0084 specialCmd = ""; 0085 done = false; 0086 opsitePath = nullptr; 0087 } 0088 0089 CMapPath::~CMapPath() 0090 { 0091 if (opsitePath) { 0092 opsitePath->setOpsitePath(nullptr); // needed to prevent endless looping 0093 delete opsitePath; 0094 } 0095 0096 if (destRoom) 0097 destRoom->getConnectingPathList()->removeAll(this); 0098 if (srcRoom) 0099 srcRoom->getPathList()->removeAll(this); 0100 } 0101 0102 void CMapPath::setDontPaintBend(int bend) 0103 { 0104 m_dontPaintBend = bend; 0105 } 0106 0107 /** This method is used to set the cords of the path */ 0108 void CMapPath::setCords(void) 0109 { 0110 QPoint pos1,pos2; 0111 CMapRoom *srcRoom = getSrcRoom(); 0112 CMapRoom *destRoom = getDestRoom(); 0113 directionTyp srcDir = getSrcDir(); 0114 directionTyp destDir = getDestDir(); 0115 0116 QPoint start; 0117 QSize halfRoomSize; 0118 0119 start.setX(srcRoom->getX() + (srcRoom->getWidth() / 2)); 0120 start.setY(srcRoom->getY() + (srcRoom->getHeight() / 2)); 0121 0122 halfRoomSize = QSize(srcRoom->getSize().width()/2,srcRoom->getSize().height()/2); 0123 getManager()->directionToCord(srcDir,halfRoomSize,&pos1); 0124 0125 pos1+=start; 0126 0127 QPoint end; 0128 0129 end.setX(destRoom->getX() + (destRoom->getWidth() / 2)); 0130 end.setY(destRoom->getY() + (destRoom->getHeight() / 2)); 0131 halfRoomSize = QSize(destRoom->getSize().width()/2,destRoom->getSize().height()/2); 0132 0133 getManager()->directionToCord(destDir,halfRoomSize,&pos2); 0134 0135 pos2+=end; 0136 0137 QRect rect(pos1,pos2); 0138 setRect(rect); 0139 setDone(false); 0140 } 0141 0142 /** Used to draw an arrow head */ 0143 void CMapPath::drawArrow(directionTyp dir,QPainter *p,QPoint end) 0144 { 0145 int x1=0,x2=0,y1=0,y2=0; 0146 QPolygon cords(3); 0147 0148 switch (dir) 0149 { 0150 case NORTH : x1=end.x()-3; x2=end.x()+3; y1=end.y()-3; y2=end.y()-3; break; 0151 case SOUTH : x1=end.x()-3; x2=end.x()+3; y1=end.y()+3; y2=end.y()+3; break; 0152 case WEST : x1=end.x()-3; x2=end.x()-3; y1=end.y()-3; y2=end.y()+3; break; 0153 case EAST : x1=end.x()+3; x2=end.x()+3; y1=end.y()-3; y2=end.y()+3; break; 0154 case NORTHEAST : x1=end.x(); x2=end.x()+4; y1=end.y()-4; y2=end.y(); break; 0155 case SOUTHEAST : x1=end.x(); x2=end.x()+4; y1=end.y()+4; y2=end.y(); break; 0156 case SOUTHWEST : x1=end.x(); x2=end.x()-4; y1=end.y()+4; y2=end.y(); break; 0157 case NORTHWEST : x1=end.x(); x2=end.x()-4; y1=end.y()-4; y2=end.y(); break; 0158 case UP : break; 0159 case DOWN : break; 0160 case SPECIAL : break; 0161 } 0162 0163 // Draw the arrow head to indicate the direction of the path 0164 cords.setPoint(0,end); 0165 cords.setPoint(1,x1,y1); 0166 cords.setPoint(2,x2,y2); 0167 p->drawPolygon(cords.constData(), 3, Qt::OddEvenFill); 0168 } 0169 0170 QPoint CMapPath::getIndent(directionTyp dir,QPoint pos) 0171 { 0172 int x=0,y=0; 0173 int posx = pos.x(); 0174 int posy = pos.y(); 0175 0176 switch (dir) 0177 { 0178 case NORTH : x = posx ; y=posy-5; break; 0179 case SOUTH : x = posx ; y=posy+5; break; 0180 case WEST : x = posx-5; y=posy ; break; 0181 case EAST : x = posx+5; y=posy ; break; 0182 case NORTHEAST : x = posx+5; y=posy-5; break; 0183 case SOUTHEAST : x = posx+5; y=posy+5; break; 0184 case SOUTHWEST : x = posx-5; y=posy+5; break; 0185 case NORTHWEST : x = posx-5; y=posy-5; break; 0186 case UP : break; 0187 case DOWN : break; 0188 case SPECIAL : break; 0189 } 0190 0191 return QPoint(x,y); 0192 } 0193 0194 /** This method is used to calcualte the distance from a path segment */ 0195 int CMapPath::getDistance (int x,int y,int x1,int x2,int y1,int y2) 0196 { 0197 int a = y1 - y2; 0198 int b = -(x1 - x2); 0199 0200 int d = (int)(( (x - x2) * a + (y-y2) * b) / sqrt (a*a + b*b)); 0201 0202 return abs(d); 0203 } 0204 0205 /** Set a pointer to the destination room */ 0206 void CMapPath::setDestRoom(CMapRoom *DestRoom) 0207 { 0208 destRoom = DestRoom; 0209 } 0210 0211 /** Set a pointer to the source room */ 0212 void CMapPath::setSrcRoom(CMapRoom *SrcRoom) 0213 { 0214 srcRoom = SrcRoom; 0215 } 0216 0217 /** Set the start and finish directrions of the path */ 0218 void CMapPath::setSrcDir(directionTyp SrcDir) 0219 { 0220 srcDir = SrcDir; 0221 } 0222 0223 void CMapPath::setDestDir(directionTyp DestDir) 0224 { 0225 destDir = DestDir; 0226 } 0227 0228 void CMapPath::makeOneWay() { 0229 CMapPath *path = getOpsitePath(); 0230 if (!path) return; 0231 path->setOpsitePath(nullptr); // so it doesn't delete us too 0232 delete path; 0233 } 0234 0235 void CMapPath::makeTwoWay() 0236 { 0237 if (opsitePath) return; 0238 0239 CMapPath *newPath = new CMapPath(getManager(), destRoom, destDir, srcRoom, srcDir, false); 0240 setOpsitePath(newPath); 0241 newPath->setOpsitePath(this); 0242 if (bSpecialExit) 0243 newPath->setSpecialCmd(specialCmd); 0244 } 0245 0246 directionTyp CMapPath::generatePath() 0247 { 0248 tempPathCords.clear(); 0249 0250 QPoint start = getLowPos(); 0251 QPoint end = getHighPos(); 0252 0253 directionTyp destDir = getDestDir(); 0254 0255 QPoint indent1 = getIndent(getSrcDir(),start); 0256 0257 QPoint indent2 = getIndent(destDir,end); 0258 0259 tempPathCords.append(start); 0260 tempPathCords.append(indent1); 0261 0262 for( PointList::Iterator point = bendList.begin(); point != bendList.end(); ++point ) 0263 { 0264 tempPathCords.append(*point); 0265 } 0266 0267 tempPathCords.append(indent2); 0268 tempPathCords.append(end); 0269 0270 return destDir; 0271 } 0272 0273 /** Used to draw the path */ 0274 void CMapPath::drawPath(QPainter *p,CMapZone *zone,QPoint offset,QColor color,int editBox,QPoint editPos) 0275 { 0276 directionTyp tempDestDir = generatePath(); 0277 0278 p->setPen(color); 0279 p->setBrush(color); 0280 0281 // If the path has not already been then draw it 0282 if (!getDone()) 0283 { 0284 if (tempPathCords.count()>1) 0285 { 0286 QPoint temp = tempPathCords.at(1); 0287 0288 int count = 0; 0289 0290 for( PointList::Iterator point = tempPathCords.begin(); point != tempPathCords.end(); ++point ) 0291 { 0292 0293 if (editBox > 0 && count==editBox + 1) 0294 { 0295 p->drawLine(temp + offset,editPos + offset); 0296 } 0297 else if (editBox > 0 && count==editBox + 2) 0298 { 0299 p->drawLine(editPos + offset,(*point) + offset); 0300 } 0301 else 0302 { 0303 if (editBox == 0 && m_dontPaintBend == 0) 0304 { 0305 p->drawLine(temp + offset,(*point) + offset); 0306 } 0307 else 0308 { 0309 if (count != m_dontPaintBend+1 && count != m_dontPaintBend + 2) 0310 { 0311 p->drawLine(temp + offset,(*point) + offset); 0312 } 0313 } 0314 } 0315 temp = *point; 0316 count++; 0317 } 0318 } 0319 0320 if (getEditMode()) 0321 { 0322 int count = 0; 0323 p->setPen(getManager()->getMapData()->editColor); 0324 p->setBrush(getManager()->getMapData()->editColor); 0325 for( PointList::Iterator point = tempPathCords.begin(); point != tempPathCords.end(); ++point ) 0326 { 0327 if (count>1 && count < (int)tempPathCords.count()-2) 0328 { 0329 if (editBox > 0 && count==editBox + 2) 0330 { 0331 p->drawRect(editPos.x()-3,editPos.y()-3,6,6); 0332 } 0333 else 0334 { 0335 if (editBox == 0 && m_dontPaintBend == 0) 0336 { 0337 p->drawRect((*point).x()-3,(*point).y()-3,6,6); 0338 } 0339 else 0340 { 0341 if (count != m_dontPaintBend+1) 0342 { 0343 p->drawRect((*point).x()-3,(*point).y()-3,6,6); 0344 } 0345 } 0346 } 0347 } 0348 count ++; 0349 } 0350 } 0351 0352 } 0353 0354 p->setPen(color); 0355 p->setBrush(color); 0356 0357 // Draw the arrow head of the path 0358 drawArrow(tempDestDir,p,tempPathCords.last() + offset); 0359 0360 if (getDestRoom()->getZone()!=zone) 0361 { 0362 if (getOpsitePath()) 0363 drawArrow(getSrcDir(),p,tempPathCords.first() + offset); 0364 } 0365 0366 // Mark this path and the opsite (two way path) as having been drawn 0367 setDone(true); 0368 0369 if (getOpsitePath()) 0370 { 0371 getOpsitePath()->setDone(true); 0372 } 0373 } 0374 0375 0376 0377 /** Used to paint the element at a given location and size 0378 * @param p The painter to paint the element to 0379 * @param pos The position to paint the elmenet 0380 * @param size The size the element should be draw 0381 * @param zone The current zone being viewed */ 0382 void CMapPath::paintElementResize(QPainter *p,QPoint,QSize,CMapZone *zone) 0383 { 0384 if (srcDir == UP || srcDir == DOWN || destDir == UP || destDir == DOWN || srcDir==SPECIAL || destDir==SPECIAL) return; 0385 0386 // Get start and end points of the path 0387 drawPath(p,zone,QPoint(0,0),getManager()->getMapData()->defaultPathColor); 0388 0389 if (getSelected()) 0390 { 0391 p->setPen(getManager()->getMapData()->selectedColor); 0392 p->setBrush(getManager()->getMapData()->selectedColor); 0393 p->drawRect(tempPathCords.first().x()-3,tempPathCords.first().y()-3,6,6); 0394 p->drawRect(tempPathCords.last().x()-3,tempPathCords.last().y()-3,6,6); 0395 } 0396 } 0397 0398 /** Used to find out if the mouse is in the element */ 0399 bool CMapPath::mouseInElement(QPoint mousePos) 0400 { 0401 if (srcDir == UP || srcDir == DOWN || srcDir==SPECIAL) return false; 0402 0403 //FIXME_jp: Handle zone paths that have been termintated 0404 generatePath(); 0405 0406 if (tempPathCords.count()>1) 0407 { 0408 QPoint temp = tempPathCords.at(1); 0409 0410 for( PointList::Iterator point = tempPathCords.begin(); point != tempPathCords.end(); ++point ) 0411 { 0412 QPoint pos1 = temp; 0413 QPoint pos2 = *point; 0414 0415 QRect rect = getBoundRectOfSeg(pos1,pos2); 0416 0417 QRegion region(rect,QRegion::Rectangle); 0418 0419 if (region.contains(mousePos)) 0420 { 0421 int distance = getDistance(mousePos.x(),mousePos.y(),pos1.x(),pos2.x(),pos1.y(),pos2.y()); 0422 0423 return (distance <= 5); 0424 } 0425 0426 temp = *point; 0427 } 0428 } 0429 return false; 0430 } 0431 0432 QRect CMapPath::getBoundRectOfSeg(QPoint pos1,QPoint pos2) 0433 { 0434 QRect rect; 0435 0436 if (pos1.x() == pos2.x()) 0437 { 0438 pos1.setX(pos1.x()-5); 0439 pos2.setX(pos2.x()+5); 0440 } 0441 0442 if (pos1.y() == pos2.y()){ 0443 0444 pos1.setY(pos1.y()-5); 0445 pos2.setY(pos2.y()+5); 0446 } 0447 0448 if (pos1.y()>pos2.y()) 0449 { 0450 rect.setBottom(pos1.y()); 0451 rect.setTop(pos2.y()); 0452 } 0453 else 0454 { 0455 rect.setTop(pos1.y()); 0456 rect.setBottom(pos2.y()); 0457 } 0458 0459 if (pos1.x()>pos2.x()) 0460 { 0461 rect.setRight(pos1.x()); 0462 rect.setLeft(pos2.x()); 0463 } 0464 else 0465 { 0466 rect.setLeft(pos1.x()); 0467 rect.setRight(pos2.x()); 0468 } 0469 0470 0471 return rect; 0472 } 0473 0474 void CMapPath::paint(QPainter *p,CMapZone *zone) 0475 { 0476 if (srcDir == UP || srcDir == DOWN || destDir == UP || destDir == DOWN || srcDir==SPECIAL || destDir==SPECIAL) return; 0477 0478 CMapElement::paint(p,zone); 0479 } 0480 0481 void CMapPath::resizePaint(QPoint,QPainter *,CMapZone *,int) 0482 { 0483 } 0484 0485 void CMapPath::editPaint(QPoint pos,QPainter *p,CMapZone *zone,int editBox) 0486 { 0487 if (srcDir == UP || srcDir == DOWN || destDir == UP || destDir == DOWN || srcDir==SPECIAL || destDir==SPECIAL) return; 0488 0489 setDone(false); 0490 drawPath(p,zone,QPoint (0,0),getManager()->getMapData()->defaultPathColor,editBox,pos); 0491 } 0492 0493 0494 void CMapPath::dragPaint(QPoint offset,QPainter *p,CMapZone *zone) 0495 { 0496 if (srcDir == UP || srcDir == DOWN || destDir == UP || destDir == DOWN || srcDir==SPECIAL || destDir==SPECIAL) return; 0497 0498 if (getSrcRoom()->getSelected() && getDestRoom()->getSelected()) 0499 { 0500 drawPath(p,zone,offset,getManager()->getMapData()->defaultPathColor); 0501 } 0502 } 0503 0504 void CMapPath::lowerPaint(QPainter *p,CMapZone *zone) 0505 { 0506 if (srcDir == UP || srcDir == DOWN || destDir == UP || destDir == DOWN || srcDir==SPECIAL || destDir==SPECIAL) return; 0507 0508 // Get start and end points of the path 0509 drawPath(p,zone,QPoint(-5,-5),getManager()->getMapData()->lowerPathColor); 0510 } 0511 0512 void CMapPath::higherPaint(QPainter *p,CMapZone *zone) 0513 { 0514 if (srcDir == UP || srcDir == DOWN || destDir == UP || destDir == DOWN || srcDir==SPECIAL || destDir==SPECIAL) return; 0515 0516 // Get start and end points of the path 0517 drawPath(p,zone,QPoint(5,5),getManager()->getMapData()->higherPathColor); 0518 } 0519 0520 /** Used to create a deep copy of the path */ 0521 CMapElement *CMapPath::copy(void) 0522 { 0523 CMapPath *path = new CMapPath(getManager(),getSrcRoom(),getSrcDir(),getDestRoom(),getDestDir(),getOpsitePath()); 0524 0525 path->setAfterCommand(getAfterCommand()); 0526 path->setBeforeCommand(getBeforeCommand()); 0527 path->setSpecialCmd(getSpecialCmd()); 0528 path->setSpecialExit(getSpecialExit()); 0529 0530 for( PointList::Iterator bend = bendList.begin(); bend != bendList.end(); ++bend ) 0531 { 0532 path->addBend(*bend); 0533 } 0534 0535 return path; 0536 } 0537 0538 /** Used to add a bend to the path */ 0539 int CMapPath::addBend(QPoint pos) 0540 { 0541 if (bendList.contains(pos)) 0542 return -1; 0543 0544 if (bendList.count()==0) 0545 { 0546 bendList.append(pos); 0547 return bendList.count()-1; 0548 } 0549 else 0550 { 0551 int x1 = getX(); 0552 int y1 = getY(); 0553 int x2 = getHighX(); 0554 int y2 = getHighY(); 0555 0556 QPoint pos1 = getIndent(getSrcDir(),QPoint (x1,y1)); 0557 0558 x1=pos1.x(),y1=pos1.y(); 0559 int count = 0; 0560 0561 for( PointList::Iterator point = bendList.begin(); point != bendList.end(); ++point ) 0562 { 0563 x2 = (*point).x(); 0564 y2 = (*point).y(); 0565 if (x1 == x2) 0566 { 0567 x1-=3; 0568 x2+=3; 0569 } 0570 0571 if (y1 == y2) 0572 { 0573 y1-=3; 0574 y2+=3; 0575 } 0576 0577 int x1_1 = x1 < x2 ? x1 : x2; 0578 int y1_1 = y1 < y2 ? y1 : y2; 0579 int x2_1 = x1 >= x2 ? x1 : x2; 0580 int y2_1 = y1 >= y2 ? y1 : y2; 0581 0582 QRegion r(x1_1,y1_1,x2_1-x1_1,y2_1-y1_1); 0583 0584 if (r.contains(pos)) 0585 { 0586 bendList.insert(count, pos); 0587 return count; 0588 } 0589 x1 = (*point).x(); 0590 y1 = (*point).y(); 0591 count++; 0592 } 0593 bendList.append(pos); 0594 return bendList.count()-1; 0595 } 0596 } 0597 0598 /** Used to add a bend to the path */ 0599 void CMapPath::addBendWithUndo(QPoint pos) 0600 { 0601 if (bendList.contains(pos)) 0602 return; 0603 0604 CMapCmdElementProperties *cmdAddBend = new CMapCmdElementProperties(getManager(),i18n("Add Bend"),this); 0605 cmdAddBend->getNewProperties().writeEntry("AddBend",pos); 0606 cmdAddBend->getOrgProperties().writeEntry("DelBend",pos); 0607 getManager()->addCommand(cmdAddBend); 0608 } 0609 0610 /** Used to move a bend to a new position */ 0611 void CMapPath::moveBendWithUndo(int bend, QPoint pos) 0612 { 0613 if (bend>0 && bend-1 < (int)bendList.count()) 0614 { 0615 QPoint oldPos = bendList.at(bend-1); 0616 CMapCmdElementProperties *cmdMoveBend = new CMapCmdElementProperties(getManager(),i18n("Move Bend"),this); 0617 cmdMoveBend->getNewProperties().writeEntry("MoveBendPos",pos); 0618 cmdMoveBend->getNewProperties().writeEntry("MoveBendBend",bend); 0619 cmdMoveBend->getOrgProperties().writeEntry("MoveBendPos",oldPos); 0620 cmdMoveBend->getOrgProperties().writeEntry("MoveBendBend",bend); 0621 getManager()->addCommand(cmdMoveBend); 0622 } 0623 } 0624 0625 /** This method is used to delete bends from a path 0626 * @param seg The path segment number to delete */ 0627 void CMapPath::deletePathSegWithUndo(int seg) 0628 { 0629 QPoint bend = deletePathSeg(seg); 0630 0631 CMapCmdElementProperties *cmdDeleteBend = new CMapCmdElementProperties(getManager(),i18n("Delete Path Segment"),this); 0632 cmdDeleteBend->getNewProperties().writeEntry("DelBend",bend); 0633 cmdDeleteBend->getOrgProperties().writeEntry("AddBend",bend); 0634 getManager()->addCommand(cmdDeleteBend); 0635 } 0636 0637 void CMapPath::deleteBend(QPoint bend) 0638 { 0639 bendList.removeAll(bend); 0640 } 0641 0642 /** Used to load the properties of the element from a list of properties */ 0643 void CMapPath::loadProperties(KConfigGroup grp) 0644 { 0645 CMapElement::loadProperties(grp); 0646 0647 setAfterCommand(grp.readEntry("SrcAfterCommand",getAfterCommand())); 0648 setBeforeCommand(grp.readEntry("SrcBeforeCommand",getBeforeCommand())); 0649 setSpecialCmd(grp.readEntry("SpecialCmdSrc",getSpecialCmd())); 0650 setSpecialExit(grp.readEntry("SpecialExit",getSpecialExit())); 0651 setSrcDir((directionTyp)grp.readEntry("SrcDir",(int)getSrcDir())); 0652 setDestDir((directionTyp)grp.readEntry("DestDir",(int)getDestDir())); 0653 setCords(); 0654 0655 if (grp.readEntry("PathTwoWay", getOpsitePath() != nullptr)) 0656 makeTwoWay(); 0657 else 0658 makeOneWay(); 0659 0660 CMapPath *opposite = getOpsitePath(); 0661 if (opposite) 0662 { 0663 opposite->setAfterCommand(grp.readEntry("DestAfterCommand",opposite->getAfterCommand())); 0664 opposite->setBeforeCommand(grp.readEntry("DestBeforeCommand",opposite->getBeforeCommand())); 0665 opposite->setSrcDir((directionTyp)grp.readEntry("DestDir",(int)opposite->getSrcDir())); 0666 opposite->setDestDir((directionTyp)grp.readEntry("SrcDir",(int)opposite->getDestDir())); 0667 opposite->setSpecialCmd(grp.readEntry("SpecialCmdDest",opposite->getSpecialCmd())); 0668 opposite->setSpecialExit(grp.readEntry("SpecialExit",opposite->getSpecialExit())); 0669 opposite->setCords(); 0670 } 0671 0672 if (grp.hasKey("AddBend")) 0673 { 0674 QPoint bend(0,0); 0675 bend = grp.readEntry("AddBend",bend); 0676 addBend(bend); 0677 } 0678 0679 if (grp.hasKey("DelBend")) 0680 { 0681 QPoint bend(0,0); 0682 bend = grp.readEntry("DelBend",bend); 0683 deleteBend(bend); 0684 } 0685 0686 if (grp.hasKey("MoveBendBend")) 0687 { 0688 QPoint pos(0,0); 0689 pos = grp.readEntry("MoveBendPos",pos); 0690 int bend = grp.readEntry("MoveBendBend",-1); 0691 moveBend(bend,pos); 0692 } 0693 0694 if (grp.hasKey("DeletePathSeg")) 0695 { 0696 int seg = grp.readEntry("DeletePathSeg", 0); 0697 deletePathSeg(seg); 0698 } 0699 } 0700 0701 /** Used to save the properties of the element to a list of properties */ 0702 void CMapPath::saveProperties(KConfigGroup grp) 0703 { 0704 // FIXME_jp : Make sure twoway paths are handled correctly 0705 CMapElement::saveProperties(grp); 0706 0707 grp.writeEntry("SrcAfterCommand",getAfterCommand()); 0708 grp.writeEntry("SrcBeforeCommand",getBeforeCommand()); 0709 grp.writeEntry("SpecialCmdSrc",getSpecialCmd()); 0710 grp.writeEntry("SpecialExit",getSpecialExit()); 0711 grp.writeEntry("SrcDir",(int)getSrcDir()); 0712 grp.writeEntry("DestDir",(int)getDestDir()); 0713 grp.writeEntry("SrcRoom",getSrcRoom()->getRoomID()); 0714 grp.writeEntry("SrcZone",getSrcRoom()->getZone()->getZoneID()); 0715 grp.writeEntry("SrcLevel",getSrcRoom()->getLevel()->getLevelID()); 0716 grp.writeEntry("DestRoom",getDestRoom()->getRoomID()); 0717 grp.writeEntry("DestZone",getDestRoom()->getZone()->getZoneID()); 0718 grp.writeEntry("DestLevel",getDestRoom()->getLevel()->getLevelID()); 0719 0720 if (getOpsitePath()) 0721 { 0722 grp.writeEntry("PathTwoWay",true); 0723 grp.writeEntry("DestAfterCommand",getOpsitePath()->getAfterCommand()); 0724 grp.writeEntry("DestBeforeCommand",getOpsitePath()->getBeforeCommand()); 0725 grp.writeEntry("SpecialCmdDest",getOpsitePath()->getSpecialCmd()); 0726 } 0727 else 0728 { 0729 grp.writeEntry("PathTwoWay",false); 0730 } 0731 } 0732 0733 /** Used to save the element as an XML object 0734 * @param properties The XML object to save the properties too 0735 * @param doc The XML Document */ 0736 void CMapPath::saveQDomElement(QDomDocument *doc,QDomElement *properties) 0737 { 0738 CMapElement::saveQDomElement(doc,properties); 0739 0740 properties->setAttribute("AfterCommand",getAfterCommand()); 0741 properties->setAttribute("BeforeCommand",getBeforeCommand()); 0742 properties->setAttribute("SpecialCmd",getSpecialCmd()); 0743 writeBool(properties,"SpecialExit",getSpecialExit()); 0744 writeInt(doc,properties,"SrcDir",(int)getSrcDir()); 0745 writeInt(doc,properties,"DestDir",(int)getDestDir()); 0746 writeInt(doc,properties,"SrcRoom",getSrcRoom()->getRoomID()); 0747 writeInt(doc,properties,"SrcZone",getSrcRoom()->getZone()->getZoneID()); 0748 writeInt(doc,properties,"SrcLevel",getSrcRoom()->getLevel()->getLevelID()); 0749 writeInt(doc,properties,"DestRoom",getDestRoom()->getRoomID()); 0750 writeInt(doc,properties,"DestZone",getDestRoom()->getZone()->getZoneID()); 0751 writeInt(doc,properties,"DestLevel",getDestRoom()->getLevel()->getLevelID()); 0752 0753 QDomElement bendsNode = doc->createElement ("bends"); 0754 properties->appendChild(bendsNode); 0755 0756 for( PointList::Iterator bend = bendList.begin(); bend != bendList.end(); ++bend ) 0757 { 0758 QDomElement bendNode = doc->createElement ("bend"); 0759 0760 writeInt(doc,&bendNode,"X",(*bend).x()); 0761 writeInt(doc,&bendNode,"Y",(*bend).y()); 0762 bendsNode.appendChild(bendNode); 0763 } 0764 } 0765 0766 /** Used to load the properties from a XML object 0767 * @param properties The XML object to load the properties from */ 0768 void CMapPath::loadQDomElement(QDomElement *properties) 0769 { 0770 CMapElement::loadQDomElement(properties); 0771 setAfterCommand(properties->attribute("AfterCommand",getAfterCommand())); 0772 setBeforeCommand(properties->attribute("BeforeCommand",getAfterCommand())); 0773 setSpecialCmd(properties->attribute("SpecialCmd",getSpecialCmd())); 0774 setSpecialExit(readBool(properties,"SpecialExit",getSpecialExit())); 0775 0776 QDomNode n = properties->namedItem("bends"); 0777 if (!n.isNull()) 0778 { 0779 QDomElement bendsNode = n.toElement(); 0780 if (!bendsNode.isNull() ) 0781 { 0782 QDomNode n1 = bendsNode.firstChild(); 0783 while (!n1.isNull() ) 0784 { 0785 QDomElement bendNode = n1.toElement(); 0786 0787 if (!bendNode.isNull() ) 0788 { 0789 int x=readInt(&bendNode,"X",-1); 0790 int y=readInt(&bendNode,"X",-1); 0791 0792 if (x!=-1 && y!=-1) 0793 { 0794 addBend(QPoint(x,y)); 0795 } 0796 } 0797 0798 n1 = n1.nextSibling(); 0799 } 0800 } 0801 } 0802 0803 //TODO_jp : write path bends 0804 0805 } 0806 0807 void CMapPath::moveBy(QPoint offset) 0808 { 0809 if (getSrcRoom()->getSelected() && getDestRoom()->getSelected()) 0810 { 0811 0812 for( PointList::Iterator point = bendList.begin(); point != bendList.end(); ++point ) 0813 { 0814 (*point)+=offset; 0815 } 0816 } 0817 } 0818 0819 /** This method is used to calculate the positions of the resize handles */ 0820 void CMapPath::generateResizePositions(void) 0821 { 0822 resizePos.clear(); 0823 resizePos.append(QRect(tempPathCords.first().x()-3,tempPathCords.first().y()-3,7,7)); 0824 resizePos.append(QRect(tempPathCords.last().x()-3,tempPathCords.last().y()-3,7,7)); 0825 0826 } 0827 0828 /** Used to find out if the mouse is in the resize box 0829 * @param mousePos The position of the mouse pointer 0830 * @param currentZone A pointer to the current zone 0831 * @return the ID of the resize box, or 0 if not in any */ 0832 int CMapPath::mouseInResize(QPoint ,CMapZone *) 0833 { 0834 return 0; 0835 } 0836 0837 /** Used to find out if the mosuse is in the edit box of the path 0838 * @param mousePos The position of the mouse pointer 0839 * @param currentZone A pointer to the current zone 0840 * @return the ID of the edit box, or 0 if not in any */ 0841 int CMapPath::mouseInEditBox(QPoint mousePos ,CMapZone *) 0842 { 0843 if (getEditMode()) 0844 { 0845 int count = 1; 0846 for( PointList::Iterator point = bendList.begin(); point != bendList.end(); ++point ) 0847 { 0848 QRegion r((*point).x()-3,(*point).y()-3,6,6); 0849 if (r.contains(mousePos)) 0850 { 0851 return count; 0852 } 0853 count ++; 0854 } 0855 } 0856 0857 return 0; 0858 } 0859 0860 /** Used to move a bend to a new position */ 0861 void CMapPath::moveBend(int bend, QPoint pos) 0862 { 0863 if (bend>0 && bend-1 < (int)bendList.count()) 0864 { 0865 bendList.replace(bend-1, pos); 0866 getManager()->changedElement(this); 0867 } 0868 } 0869 0870 /** This method is used to delete bends from a path 0871 * @param seg The path segment number to delete */ 0872 QPoint CMapPath::deletePathSeg(int seg) 0873 { 0874 QPoint deletedPos; 0875 0876 for( PointList::Iterator point = bendList.begin(); point != bendList.end(); ++point ) 0877 { 0878 kDebug() << "Bend : " << (*point).x() << "," << (*point).y(); 0879 } 0880 0881 if (seg > (int) bendList.count()) seg = bendList.count(); 0882 deletedPos = bendList.at(seg - 1); 0883 return deletedPos; 0884 } 0885 0886 /** 0887 * This method is used to find out if the mouse pointer is in a path segment. 0888 * @param mousePos The position of the mouse 0889 * @param currentZone The current zone being viewed 0890 * @return 0 if not in any segament, otherwise return the number of the segment 0891 */ 0892 int CMapPath::mouseInPathSeg(QPoint mousePos,CMapZone *currentZone) 0893 { 0894 // Is this a inter zone path 0895 if (getSrcRoom()->getZone()!=currentZone || getDestRoom()->getZone()!=currentZone) 0896 return -1; 0897 0898 if (bendList.count()==0) 0899 return -1; 0900 0901 int count = 0; 0902 int x1=tempPathCords.first().x(),y1=tempPathCords.first().y(),x2,y2; 0903 0904 for( PointList::Iterator point = tempPathCords.begin(); point != tempPathCords.end(); ++point ) 0905 { 0906 x2 = (*point).x(); 0907 y2 = (*point).y(); 0908 0909 if (count > 1 && count < (int)tempPathCords.count()-1) 0910 { 0911 int startx = x1-5; 0912 int endx = x2+5; 0913 int starty = y1-5; 0914 int endy = y2+5; 0915 0916 QRegion r(startx,starty,endx-startx,endy-starty); 0917 0918 if (r.contains(mousePos)) 0919 { 0920 0921 int d = getDistance (mousePos.x(),mousePos.y(),startx,endx,starty,endy); 0922 0923 if (d<=5) 0924 { 0925 return count -1; 0926 } 0927 } 0928 } 0929 0930 count++; 0931 0932 x1 = x2; 0933 y1 = y2; 0934 } 0935 0936 return -1; 0937 }