File indexing completed on 2024-04-21 04:03:09

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 }