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