File indexing completed on 2024-12-08 06:46:39
0001 /********************************************f******************************* 0002 mapmanager.cpp - description 0003 ------------------- 0004 begin : Wed Mar 7 2001 0005 copyright : (C) 2001 by KMud Development Team 0006 (C) 2007 Tomas Mecir <kmuddy@kmuddy.com> 0007 email : kmud-devel@kmud.de 0008 ***************************************************************************/ 0009 0010 /*************************************************************************** 0011 * * 0012 * This program is free software; you can redistribute it and/or modify * 0013 * it under the terms of the GNU General Public License as published by * 0014 * the Free Software Foundation; either version 2 of the License, or * 0015 * (at your option) any later version. * 0016 * * 0017 ***************************************************************************/ 0018 0019 #include "cmapmanager.h" 0020 0021 #include <KLocalizedString> 0022 #include <kservicetypetrader.h> 0023 #include <kmessagebox.h> 0024 #include <kstandardaction.h> 0025 #include <kpagedialog.h> 0026 0027 #include <QDebug> 0028 #include <QIcon> 0029 #include <QQueue> 0030 #include <QStandardPaths> 0031 #include <QStatusBar> 0032 #include <QTimer> 0033 #include <QUndoStack> 0034 0035 #include "cmapzone.h" 0036 #include "cmappath.h" 0037 #include "cmaptext.h" 0038 #include "cmaproom.h" 0039 #include "cmapview.h" 0040 #include "cmaplevel.h" 0041 #include "cmapview.h" 0042 #include "cmaptoolbase.h" 0043 #include "cmappluginbase.h" 0044 #include "cmapzonemanager.h" 0045 0046 #include "cmapcmdelementcreate.h" 0047 #include "cmapcmdelementdelete.h" 0048 #include "cmapcmdelementproperties.h" 0049 #include "cmapcmdgroup.h" 0050 #include "cmapcmdmovemap.h" 0051 #include "cmapcmdmoveplayer.h" 0052 #include "cmapcmdleveldelete.h" 0053 #include "cmapcmdlevelcreate.h" 0054 #include "cmapcmdtogglepathtwoway.h" 0055 #include "cmapfilefilterbase.h" 0056 0057 #include "kmuddy_mapper.h" 0058 0059 #include "filefilters/cmapfilefilterxml.h" 0060 0061 #include "dialogs/dlgmaproomproperties.h" 0062 #include "dialogs/dlgmappathproperties.h" 0063 #include "dialogs/dlgmaptextproperties.h" 0064 #include "dialogs/dlgspeedwalkprogress.h" 0065 #include "dialogs/dlgmapspeedwalk.h" 0066 #include "dialogs/dlgmapcolor.h" 0067 #include "dialogs/dlgmapdirections.h" 0068 #include "dialogs/dlgmapmovement.h" 0069 0070 #include "cactionmanager.h" 0071 #include "cdialoglist.h" 0072 #include "cglobalsettings.h" 0073 #include "cstatus.h" 0074 0075 CMapManager::CMapManager (QWidget *parent, KMuddyMapper *mapper, int sessId) : 0076 cActionBase ("map-manager", 0), 0077 m_sessId (sessId), 0078 mapperPlugin (mapper) 0079 { 0080 qDebug() << "constructor begins"; 0081 0082 // register action handlers 0083 addEventHandler ("dialog-create", 50, PT_STRING); 0084 addEventHandler ("dialog-save", 50, PT_STRING); 0085 0086 mapData = new CMapData(); 0087 0088 // Setup vars 0089 loginRoom = nullptr; 0090 currentRoom = nullptr; 0091 elementEdit = nullptr; 0092 0093 /** Create undo/redo history */ 0094 commandHistory = new QUndoStack(); 0095 //FIXME_jp: Needs to be configurable 0096 commandHistory->setUndoLimit(30); 0097 commandHistory->clear(); 0098 historyGroup = nullptr; 0099 m_commandsActive = true; 0100 0101 initFileFilters(); 0102 0103 activeView = nullptr; 0104 0105 setDefaultOptions(); 0106 0107 speedwalkActive = false; 0108 0109 speedwalkProgressDlg = new DlgSpeedwalkProgress(); 0110 speedwalkProgressDlg->hide(); 0111 connect(speedwalkProgressDlg,SIGNAL(abortSpeedwalk()),this,SLOT(slotAbortSpeedwalk())); 0112 0113 m_zoneCount = 0; 0114 m_levelCount = 0; 0115 m_zoneManager = nullptr; 0116 0117 setUndoActive (false); 0118 createNewMap(); // because some things break if a map doesn't exist 0119 activeView = new CMapView(this, parent); 0120 0121 m_zoneManager = new CMapZoneManager(sessId, this); 0122 if (!m_zoneManager->zonesModel()->rowCount()) 0123 m_zoneManager->createZone (i18n ("Map #1")); 0124 m_zoneManager->loadZone(0); 0125 0126 initPlugins(); 0127 activeView->initGUI(); 0128 0129 readOptions(); 0130 0131 openMapView (); 0132 setUndoActive (true); 0133 0134 qDebug() << "constructor ends"; 0135 } 0136 0137 CMapManager::~CMapManager() 0138 { 0139 qDebug() << "CMapManager::~CMapManager() start"; 0140 removeEventHandler ("dialog-create"); 0141 removeEventHandler ("dialog-save"); 0142 0143 if (mapData) 0144 delete mapData; 0145 mapData = nullptr; 0146 delete m_zoneManager; 0147 delete activeView; 0148 0149 if (commandHistory) 0150 delete commandHistory; 0151 0152 for (CMapFileFilterBase *filter : m_fileFilter) 0153 delete filter; 0154 m_fileFilter.clear(); 0155 0156 qDebug() << "CMapManager::~CMapManager() end"; 0157 } 0158 0159 void CMapManager::eventStringHandler (QString event, int, QString &par1, const QString &) 0160 { 0161 if (event == "dialog-create") { 0162 if (par1 == "profile-prefs") 0163 createProfileConfigPanes (); 0164 else if (par1 == "app-prefs") 0165 createGlobalConfigPanes (); 0166 } 0167 if (event == "dialog-save") { 0168 if (par1 == "profile-prefs") { 0169 } else if (par1 == "app-prefs") { 0170 // TODO: the first two should be profile prefs 0171 mapDirection->slotOkPressed(); 0172 mapMovement->slotOkPressed(); 0173 0174 mapColor->slotOkPressed(); 0175 mapSpeedwalk->slotOkPressed(); 0176 saveGlobalConfig (); 0177 } 0178 } 0179 } 0180 0181 void CMapManager::createProfileConfigPanes () 0182 { 0183 /*KPageDialog *dlg = */(KPageDialog *) cDialogList::self()->getDialog ("profile-prefs"); 0184 0185 for (CMapPluginBase *plugin : pluginList) 0186 plugin->createProfileConfigPanes(); 0187 } 0188 0189 void CMapManager::createGlobalConfigPanes () 0190 { 0191 KPageDialog *dlg = (KPageDialog *) cDialogList::self()->getDialog ("app-prefs"); 0192 0193 KPageWidgetItem *item; 0194 QFrame *frmdir = new QFrame (dlg); 0195 item = dlg->addPage (frmdir, i18n ("Mapper: Directions")); 0196 item->setIcon (QIcon::fromTheme ("gear")); 0197 QFrame *frmmovement = new QFrame (dlg); 0198 item = dlg->addPage (frmmovement, i18n ("Mapper: Movement")); 0199 item->setIcon (QIcon::fromTheme ("run")); 0200 QFrame *frmcolor = new QFrame (dlg); 0201 item = dlg->addPage (frmcolor, i18n ("Mapper: Colors")); 0202 item->setIcon (QIcon::fromTheme ("colorize")); 0203 QFrame *frmspeedwalk = new QFrame (dlg); 0204 item = dlg->addPage (frmspeedwalk, i18n ("Mapper: Speedwalk")); 0205 item->setIcon (QIcon::fromTheme ("launch")); 0206 0207 QVBoxLayout *dirlayout = new QVBoxLayout (frmdir); 0208 QVBoxLayout *movementlayout = new QVBoxLayout (frmmovement); 0209 QVBoxLayout *colorlayout = new QVBoxLayout (frmcolor); 0210 QVBoxLayout *speedwalklayout = new QVBoxLayout (frmspeedwalk); 0211 mapDirection = new DlgMapDirections (this, frmdir); 0212 mapMovement = new DlgMapMovement (this, frmmovement); 0213 mapColor = new DlgMapColor(this, frmcolor); 0214 mapSpeedwalk = new DlgMapSpeedwalk(this, frmspeedwalk); 0215 dirlayout->addWidget (mapDirection); 0216 movementlayout->addWidget (mapMovement); 0217 colorlayout->addWidget (mapColor); 0218 speedwalklayout->addWidget (mapSpeedwalk); 0219 0220 for (CMapPluginBase *plugin : pluginList) 0221 plugin->createGlobalConfigPanes(); 0222 } 0223 0224 QList<CMapPropertiesPaneBase *> CMapManager::createPropertyPanes(elementTyp type,CMapElement *element,QWidget *parent) 0225 { 0226 QList<CMapPropertiesPaneBase *> res; 0227 for (CMapPluginBase *plugin : pluginList) 0228 res.append(plugin->createPropertyPanes(type, element, parent)); 0229 return res; 0230 } 0231 0232 0233 /** This will setup the import/export file filters */ 0234 void CMapManager::initFileFilters() 0235 { 0236 m_fileFilter.push_back(new CMapFileFilterXML(this)); 0237 } 0238 0239 #include "plugins/standard/cmappluginstandard.h" 0240 0241 /** Used to create the plugins */ 0242 void CMapManager::initPlugins() 0243 { 0244 int pluginCount = 0; 0245 qDebug() << "Loading Static Plugins...\n"; 0246 // These used to be plug-ins, but now I'm linking them in statically, and just pretend that they are plug-ins. 0247 // This is because linking to the mapper part is causing issues. 0248 CMapPluginBase *plugin; 0249 plugin = new CMapPluginStandard (activeView); 0250 pluginList.push_back (plugin); 0251 0252 for (CMapPluginBase *plugin : pluginList) 0253 { 0254 qDebug() << "Tools in plugin : " << plugin->getToolList()->count(); 0255 foreach (CMapToolBase *tool, *plugin->getToolList()) 0256 { 0257 toolList.push_back(tool); 0258 } 0259 0260 // getActiveView()->insertChildClient(plugin); 0261 0262 pluginCount++; 0263 } 0264 0265 qDebug() << "Finished loading " << pluginCount << " plugins\n"; 0266 qDebug() << "Finished loading " << toolList.size() << " tools\n"; 0267 0268 if (!toolList.empty()) 0269 { 0270 currentTool = toolList.front(); 0271 currentTool->setChecked(true); 0272 } 0273 else 0274 { 0275 qWarning() << "No tools loaded!\n"; 0276 currentTool = nullptr; 0277 } 0278 0279 if (pluginCount==0) 0280 { 0281 qWarning() << "No plugins loaded!\n"; 0282 } 0283 0284 qDebug() << "XML File : " << activeView->xmlFile(); 0285 } 0286 0287 /** Used to get a list of the plugins */ 0288 std::vector<CMapPluginBase *> CMapManager::getPluginList() 0289 { 0290 return pluginList; 0291 } 0292 0293 /** Used to get a pointer to the map data */ 0294 CMapData *CMapManager::getMapData() const 0295 { 0296 return mapData; 0297 } 0298 0299 CMapZone *CMapManager::getZone(bool noCreate) 0300 { 0301 CMapZone *zone = mapData->rootZone; 0302 if ((!zone) && (!noCreate)) 0303 zone = new CMapZone(this); 0304 0305 return zone; 0306 } 0307 0308 /** Used to create a new view of the map */ 0309 void CMapManager::openMapView() 0310 { 0311 if (loginRoom) 0312 activeView->showPosition(QPoint(loginRoom->getX(),loginRoom->getY()),loginRoom->getLevel()); 0313 else 0314 { 0315 CMapRoom *firstRoom = findFirstRoom(nullptr); 0316 if (firstRoom) 0317 displayLevel(firstRoom->getLevel(), true); 0318 } 0319 } 0320 0321 void CMapManager::displayLevel(CMapLevel *level, bool centerView) 0322 { 0323 CMapView *mapView = getActiveView(); 0324 mapView->showPosition(level, centerView); 0325 } 0326 0327 /** This method is used to covert cords so that they snap to the grid */ 0328 QPoint CMapManager::cordsSnapGrid(QPoint oldPos) 0329 { 0330 QPoint newPos; 0331 0332 int oldx = (int)(oldPos.x() / mapData->gridSize.width()); 0333 int oldy = (int)(oldPos.y() / mapData->gridSize.height()); 0334 newPos.setX( oldx * mapData->gridSize.width()); 0335 newPos.setY( oldy * mapData->gridSize.height()); 0336 0337 return newPos; 0338 } 0339 0340 /** 0341 * Used to create a new view of the a given level and 0342 * center the view on the given position. 0343 */ 0344 void CMapManager::openNewMapView(QPoint pos,CMapLevel *level) 0345 { 0346 CMapView *mapView = getActiveView(); 0347 mapView->showPosition(pos,level); 0348 } 0349 0350 /** Used to set properties of the view widget */ 0351 void CMapManager::setPropertiesAllViews(QCursor *cursor,bool mouseTracking) 0352 { 0353 activeView->setCursor(*cursor); 0354 activeView->setMouseTracking(mouseTracking); 0355 } 0356 0357 /** Used to unselect all the elements in a level */ 0358 void CMapManager::unselectElements(CMapLevel *level) 0359 { 0360 QList<CMapElement *> lst = level->getAllElements(); 0361 foreach (CMapElement *element, lst) 0362 { 0363 element->setSelected(false); 0364 element->setEditMode(false); 0365 } 0366 } 0367 0368 /** Used to convert a text direction to a direction type */ 0369 QString CMapManager::directionToText(directionTyp dir, QString specialCmd, bool shortName) 0370 { 0371 if ((uint)dir < NUM_DIRECTIONS) 0372 { 0373 if (shortName && ((uint)dir < NUM_DIRECTIONS / 2)) dir = (directionTyp) ((int)dir + NUM_DIRECTIONS / 2); 0374 return mapData->directions[dir]; 0375 } 0376 else 0377 { 0378 return specialCmd; 0379 } 0380 } 0381 0382 /** Used to convert a direction type to a text direction */ 0383 directionTyp CMapManager::textToDirection(QString text) 0384 { 0385 directionTyp dir = SPECIAL; 0386 0387 for (uint i = 0; i < NUM_DIRECTIONS; ++i) 0388 { 0389 if (text == mapData->directions[i]) 0390 { 0391 if (i>9) 0392 { 0393 dir = (directionTyp)(i-10); 0394 } 0395 else 0396 { 0397 dir = (directionTyp)i; 0398 } 0399 break; 0400 } 0401 } 0402 0403 return dir; 0404 } 0405 0406 /** Used to set the login room */ 0407 void CMapManager::setLoginRoom(CMapRoom *room) 0408 { 0409 openCommandGroup(i18n("Change Login Room")); 0410 if (loginRoom) 0411 { 0412 CMapCmdElementProperties *cmdRemove = new CMapCmdElementProperties(this,i18n("Remove Login Room Status"),loginRoom); 0413 cmdRemove->getOrgProperties().writeEntry("Login",true); 0414 cmdRemove->getNewProperties().writeEntry("Login",false); 0415 0416 addCommand(cmdRemove); 0417 } 0418 0419 CMapCmdElementProperties *cmdSet = new CMapCmdElementProperties(this,i18n("Set Login Room Status"),room); 0420 0421 cmdSet->getOrgProperties().writeEntry("Login",false); 0422 cmdSet->getNewProperties().writeEntry("Login",true); 0423 0424 addCommand(cmdSet); 0425 0426 closeCommandGroup(); 0427 } 0428 0429 /** Uesd to return the login room */ 0430 CMapRoom *CMapManager::getLoginRoom() 0431 { 0432 return loginRoom; 0433 } 0434 0435 /** Should only be called by CMapRoom.setCurrentRoom() */ 0436 void CMapManager::setCurrentRoomWithoutUndo(CMapRoom *room) 0437 { 0438 currentRoom = room; 0439 } 0440 0441 /** Should only be called by CMapRoom.setLoginRoom() */ 0442 void CMapManager::setLoginRoomWithoutUndo(CMapRoom *room) 0443 { 0444 loginRoom = room; 0445 } 0446 0447 0448 /** Used to set the current room */ 0449 void CMapManager::setCurrentRoom(CMapRoom *room) 0450 { 0451 openCommandGroup(i18n("Change Current Room")); 0452 0453 CMapCmdElementProperties *cmdRemove = new CMapCmdElementProperties(this,i18n("Remove Current Room Status"),currentRoom); 0454 cmdRemove->getOrgProperties().writeEntry("Current",true); 0455 cmdRemove->getNewProperties().writeEntry("Current",false); 0456 addCommand(cmdRemove); 0457 0458 CMapCmdElementProperties *cmdSet = new CMapCmdElementProperties(this,i18n("Set Current Room Status"),room); 0459 cmdSet->getOrgProperties().writeEntry("Current",false); 0460 cmdSet->getNewProperties().writeEntry("Current",true); 0461 addCommand(cmdSet); 0462 0463 closeCommandGroup(); 0464 } 0465 0466 /** Uesd to return the current room */ 0467 CMapRoom *CMapManager::getCurrentRoom() 0468 { 0469 return currentRoom; 0470 } 0471 0472 /** This method is used to find a element from a list of properties 0473 * @param properties The list of proerties 0474 * @return The element if it's found otherwise NULL */ 0475 CMapElement *CMapManager::findElement(KConfigGroup properties) 0476 { 0477 elementTyp type = (elementTyp)properties.readEntry("Type",(uint)OTHER); 0478 0479 if (type == OTHER) return nullptr; 0480 0481 if (type==PATH) 0482 { 0483 CMapLevel *srcLevel = findLevel(properties.readEntry("SrcLevel",-1)); 0484 CMapRoom *srcRoom = srcLevel->findRoom(properties.readEntry("SrcRoom",-1)); 0485 if (!srcRoom) return nullptr; 0486 directionTyp srcDir = (directionTyp)properties.readEntry("SrcDir",0); 0487 0488 QString specialCommand = properties.readEntry("SpecialCmdSrc",""); 0489 return srcRoom->getPathDirection(srcDir,specialCommand); 0490 } 0491 0492 CMapLevel *level = findLevel(properties.readEntry("Level",-5)); 0493 if (!level) return nullptr; 0494 0495 if (type == ROOM) 0496 { 0497 CMapRoom *room = level->findRoom(properties.readEntry("RoomID",-5)); 0498 return room; 0499 } 0500 0501 int x = properties.readEntry("X",-5); 0502 int y = properties.readEntry("Y",-5); 0503 0504 foreach (CMapText *text, *level->getTextList()) 0505 if ((text->getX()==x) && (text->getY()==y)) 0506 return text; 0507 0508 return nullptr; 0509 } 0510 0511 /** Used to erase the map. This will erase all elements and can't be undone */ 0512 void CMapManager::eraseMap(void) 0513 { 0514 if (!mapData->rootZone) return; 0515 0516 eraseZone(mapData->rootZone); 0517 delete mapData->rootZone; 0518 mapData->rootZone = nullptr; 0519 0520 m_zoneCount = 0; 0521 m_levelCount = 0; 0522 0523 if (activeView) activeView->setLevel(nullptr); 0524 0525 for (CMapPluginBase *plugin : pluginList) 0526 plugin->mapErased(); 0527 0528 loginRoom = nullptr; 0529 currentRoom = nullptr; 0530 elementEdit = nullptr; 0531 } 0532 0533 void CMapManager::eraseZone(CMapZone *zone) 0534 { 0535 if (zone == nullptr) 0536 return; 0537 0538 QList<CMapLevel *> levels; 0539 for (unsigned int idx = 0; idx < zone->levelCount(); ++idx) 0540 levels.append(zone->getLevel(idx)); 0541 foreach (CMapLevel *level, levels) 0542 { 0543 // TODO: this seems to not delete things correctly 0544 foreach (CMapRoom *room, *level->getRoomList()) 0545 { 0546 room->getPathList()->clear(); 0547 room->getConnectingPathList()->clear(); 0548 } 0549 level->getRoomList()->clear(); 0550 level->getTextList()->clear(); 0551 0552 delete level; 0553 } 0554 } 0555 0556 /** Create new bottom or top level depending on the given direction */ 0557 CMapLevel *CMapManager::createLevel(directionTyp dir) 0558 { 0559 CMapLevel *result = nullptr; 0560 0561 CMapCmdLevelCreate *cmd = nullptr; 0562 0563 int pos = (dir == UP) ? getZone()->levelCount() : 0; 0564 if (getUndoActive()) 0565 { 0566 cmd = new CMapCmdLevelCreate(this,i18n("Create Level"),pos); 0567 addCommand(cmd); 0568 0569 result = cmd->getLevel(); 0570 } 0571 else 0572 { 0573 result = new CMapLevel(this, pos); 0574 } 0575 0576 return result; 0577 } 0578 0579 /** This is used to find a level with a given id 0580 * @param id The id of the level to find 0581 * @return Null if no level is found otherwise a pointer to the level */ 0582 CMapLevel *CMapManager::findLevel(unsigned int id) 0583 { 0584 CMapZone *zone = getZone(); 0585 for (unsigned int idx = 0; idx < zone->levelCount(); ++idx) 0586 { 0587 CMapLevel *level = zone->getLevel(idx); 0588 if (level->getLevelID() == id) 0589 return level; 0590 } 0591 0592 return nullptr; 0593 } 0594 0595 /** Create new map */ 0596 void CMapManager::createNewMap() 0597 { 0598 // Create the root zone 0599 getMapData()->rootZone = nullptr; 0600 0601 CMapZone *zone = getZone(); 0602 0603 // Create a empty room in the first level of the new zone 0604 CMapRoom *room = CMapElementUtil::createRoom(this, QPoint(2 * mapData->gridSize.width(),2 * mapData->gridSize.height()),zone->firstLevel()); 0605 setCurrentRoomWithoutUndo(room); 0606 setLoginRoomWithoutUndo(room); 0607 0608 if (!activeView) return; 0609 0610 if (currentRoom) activeView->showPosition(currentRoom->getLowPos(),zone->firstLevel()); 0611 0612 if (activeView->getCurrentlyViewedLevel()==nullptr) 0613 activeView->showPosition(loginRoom,true); 0614 0615 for (CMapPluginBase *plugin : pluginList) 0616 plugin->newMapCreated(); 0617 0618 activeView->changed(); 0619 } 0620 0621 /** Used to create a new room that can be undone/redone 0622 * @param pos The position to create the room 0623 * @param level The level to create the room in 0624 */ 0625 void CMapManager::createRoom(QPoint pos,CMapLevel *level) 0626 { 0627 if (getUndoActive()) 0628 { 0629 KMemConfig properties; 0630 KConfigGroup props = properties.group("Properties"); 0631 props.writeEntry("Type",(int)ROOM); 0632 props.writeEntry("X",pos.x()); 0633 props.writeEntry("Y",pos.y()); 0634 props.writeEntry("Level",level->getLevelID()); 0635 CMapCmdElementCreate *command = new CMapCmdElementCreate(this,i18n("Create Room")); 0636 command->addElement(&properties); 0637 addCommand(command); 0638 } 0639 else 0640 { 0641 CMapElementUtil::createRoom(this, pos, level); 0642 } 0643 } 0644 0645 /** Used to create a new text label */ 0646 void CMapManager::createText(QPoint pos,CMapLevel *level,QString str) 0647 { 0648 if (getUndoActive()) 0649 { 0650 KMemConfig properties; 0651 KConfigGroup props = properties.group("Properties"); 0652 props.writeEntry("Type",(int)TEXT); 0653 props.writeEntry("X",pos.x()); 0654 props.writeEntry("Y",pos.y()); 0655 0656 if (level) 0657 { 0658 props.writeEntry("Level",level->getLevelID()); 0659 } 0660 0661 props.writeEntry("Text",str); 0662 0663 CMapCmdElementCreate *command = new CMapCmdElementCreate(this,i18n("Create Text")); 0664 command->addElement(&properties); 0665 addCommand(command); 0666 } 0667 else 0668 { 0669 CMapElementUtil::createText(this, pos, level, str); 0670 } 0671 } 0672 0673 /** Used to create a new text label */ 0674 void CMapManager::createText(QPoint pos,CMapLevel *level,QString str,QFont font,QColor col) 0675 { 0676 if (getUndoActive()) 0677 { 0678 KMemConfig properties; 0679 KConfigGroup props = properties.group("Properties"); 0680 props.writeEntry("Type",(int)TEXT); 0681 props.writeEntry("X",pos.x()); 0682 props.writeEntry("Y",pos.y()); 0683 if (level) 0684 { 0685 props.writeEntry("Level",level->getLevelID()); 0686 } 0687 0688 props.writeEntry("Text",str); 0689 props.writeEntry("Font",font); 0690 props.writeEntry("Color",col); 0691 0692 CMapCmdElementCreate *command = new CMapCmdElementCreate(this,i18n("Create Text")); 0693 command->addElement(&properties); 0694 addCommand(command); 0695 } 0696 else 0697 { 0698 CMapElementUtil::createText(this, pos, level, str, font, col); 0699 } 0700 } 0701 0702 0703 /** Used to create a new path*/ 0704 CMapPath *CMapManager::createPath(QPoint srcPos,CMapLevel *srcLevel,directionTyp srcDir, 0705 QPoint destPos,CMapLevel *destLevel,directionTyp destDir) 0706 { 0707 CMapRoom *room=nullptr; 0708 CMapRoom *srcRoom=nullptr; 0709 CMapRoom *destRoom=nullptr; 0710 0711 if (!srcLevel || !destLevel) 0712 return nullptr; 0713 0714 foreach (room, *srcLevel->getRoomList()) 0715 { 0716 if (room->getLowPos() == srcPos) 0717 { 0718 srcRoom = room; 0719 break; 0720 } 0721 } 0722 0723 foreach (room, *destLevel->getRoomList()) 0724 { 0725 if (room->getLowPos() == destPos) 0726 { 0727 destRoom = room; 0728 break; 0729 } 0730 } 0731 0732 return createPath(srcRoom,srcDir,destRoom,destDir); 0733 } 0734 0735 CMapPath *CMapManager::createPath(CMapRoom *srcRoom,CMapRoom *destRoom) 0736 { 0737 CMapPath *result = nullptr; 0738 0739 KMemConfig properties; 0740 KConfigGroup props = properties.group("Properties"); 0741 // Auto-set the directions if possible 0742 directionTyp srcDir = srcRoom->bestDirectionToRoom(destRoom); 0743 directionTyp destDir = getOpsiteDirection(srcDir); 0744 if (srcDir != SPECIAL) { 0745 // nothing if there is an exit already 0746 if (srcRoom->getPathDirection(srcDir, QString())) srcDir = SPECIAL; 0747 if (destRoom->getPathDirection(destDir, QString())) destDir = SPECIAL; 0748 } 0749 props.writeEntry("SrcDir", (int) srcDir); 0750 props.writeEntry("DestDir", (int) destDir); 0751 0752 DlgMapPathProperties d(this,props,false); 0753 0754 if (!d.exec()) return nullptr; 0755 0756 srcDir = (directionTyp)props.readEntry("SrcDir",0); 0757 destDir = (directionTyp)props.readEntry("DestDir",0); 0758 QString specialCmdSrc = props.readEntry("SpecialCmdSrc"); 0759 QString specialCmdDest = props.readEntry("SpecialCmdDest"); 0760 0761 if (srcRoom->getPathDirection(srcDir,specialCmdSrc) || destRoom->getPathDirection(destDir,specialCmdDest)) 0762 { 0763 KMessageBox::information (nullptr,i18n("A path already exists at this location"),i18n("KMuddy Mapper")); 0764 return nullptr; 0765 } 0766 0767 // create 0768 props.writeEntry("Type",(int)PATH); 0769 props.writeEntry("SrcRoom",srcRoom->getRoomID()); 0770 props.writeEntry("SrcDir",(int)srcDir); 0771 props.writeEntry("SrcLevel",srcRoom->getLevel()->getLevelID()); 0772 props.writeEntry("DestRoom",destRoom->getRoomID()); 0773 props.writeEntry("DestDir",(int)destDir); 0774 props.writeEntry("DestLevel",destRoom->getLevel()->getLevelID()); 0775 0776 CMapCmdElementCreate *command = new CMapCmdElementCreate(this,i18n("Create Path")); 0777 command->addElement(&properties); 0778 0779 addCommand(command); 0780 0781 QList<CMapElement *> *elements=command->getElements(); 0782 0783 foreach (CMapElement *el, *elements) 0784 if (el->getElementType()==PATH) 0785 result = (CMapPath *)el; 0786 0787 return result; 0788 } 0789 0790 0791 /** Used to create a new path*/ 0792 CMapPath *CMapManager::createPath (CMapRoom *srcRoom,directionTyp srcDir,CMapRoom *destRoom,directionTyp destDir,bool undoable, bool twoWay) 0793 { 0794 // FIXME_jp : Allow this to call lowlevel mapper methods when undo is not active 0795 // but becarefull of second stage stuff 0796 0797 CMapPath *result = nullptr; 0798 0799 KMemConfig properties; 0800 KConfigGroup props = properties.group("Properties"); 0801 props.writeEntry("Type",(int)PATH); 0802 props.writeEntry("SrcRoom",srcRoom->getRoomID()); 0803 props.writeEntry("SrcLevel",srcRoom->getLevel()->getLevelID()); 0804 props.writeEntry("SrcDir",(int)srcDir); 0805 props.writeEntry("DestRoom",destRoom->getRoomID()); 0806 props.writeEntry("DestLevel",destRoom->getLevel()->getLevelID()); 0807 props.writeEntry("DestDir",(int)destDir); 0808 props.writeEntry("PathTwoWay",twoWay); 0809 0810 CMapCmdElementCreate *command = new CMapCmdElementCreate(this,i18n("Create Path")); 0811 command->addElement(&properties); 0812 bool active = getUndoActive(); 0813 if (!undoable) 0814 { 0815 setUndoActive(false); 0816 } 0817 0818 addCommand(command); 0819 0820 if (!undoable) 0821 { 0822 setUndoActive(active); 0823 } 0824 0825 QList<CMapElement *> *elements=command->getElements(); 0826 foreach (CMapElement *el, *elements) 0827 if (el->getElementType()==PATH) 0828 result = (CMapPath *)el; 0829 0830 return result; 0831 } 0832 0833 0834 /** Find the first room in the map, if one can't be found then create one */ 0835 CMapRoom *CMapManager::findFirstRoom(CMapRoom *existingRoom) 0836 { 0837 CMapZone *zone = getZone(); 0838 for (unsigned int idx = 0; idx < zone->levelCount(); ++idx) 0839 { 0840 CMapLevel *level = zone->getLevel(idx); 0841 foreach (CMapRoom *room, *level->getRoomList()) 0842 if (room!=existingRoom) 0843 return room; 0844 } 0845 0846 // If we get to this point then no room was found so create one 0847 return CMapElementUtil::createRoom(this, QPoint(2 * mapData->gridSize.width(),2 * mapData->gridSize.height()), getZone()->firstLevel()); 0848 } 0849 0850 void CMapManager::deleteLevel(CMapLevel *level) 0851 { 0852 //FIXME_jp: Check to see what happens when all levels are deleted. 0853 // It may be nessecary to create a new one. 0854 0855 // Delete the level 0856 CMapCmdLevelDelete *cmd = new CMapCmdLevelDelete(this,i18n("Delete Level"),level); 0857 addCommand(cmd); 0858 } 0859 0860 0861 /** Check to see if a string is a valid move command 0862 * @param dirCmd The command that was typed 0863 * @return True, if a valid command otherwise false */ 0864 bool CMapManager::validMoveCmd(QString dirCmd) 0865 { 0866 if (dirCmd.isEmpty()) return false; 0867 0868 // check for directions 0869 for (uint i = 0; i < NUM_DIRECTIONS; ++i) 0870 if (mapData->directions[i] == dirCmd) 0871 return true; 0872 0873 if (currentRoom) 0874 foreach (CMapPath *path, *currentRoom->getPathList()) 0875 if (path->getSpecialExit() && (path->getSpecialCmd()==dirCmd)) 0876 return true; 0877 0878 return false; 0879 } 0880 0881 /** Used to delete a element from the map, should not be used by deleteElement as 0882 * it does not use groups */ 0883 // FIXME_jp : This method can be removed if the deleteElement method is recursive 0884 void CMapManager::deleteElementWithoutGroup(CMapElement *element,bool delOpsite) 0885 { 0886 KMemConfig properties; 0887 0888 element->saveProperties(properties.group("Properties")); 0889 0890 CMapCmdElementDelete *command = new CMapCmdElementDelete(this,i18n("Delete Element"),delOpsite); 0891 0892 command->addElement(&properties); 0893 addCommand(command); 0894 } 0895 0896 /** Used to delete a element from the map */ 0897 void CMapManager::deleteElement(CMapElement *element,bool delOpsite) 0898 { 0899 openCommandGroup(i18n("Delete Element")); 0900 0901 // If the element is a room, then we also need to delete all its paths 0902 if (element->getElementType()==ROOM) 0903 { 0904 CMapRoom *room = (CMapRoom *)element; 0905 if (room->getLinkedElement()) 0906 { 0907 deleteElementWithoutGroup(room->getLinkedElement(),true); 0908 } 0909 0910 QList<CMapPath *> wipePaths; 0911 // Delete the paths for the room 0912 foreach (CMapPath *path, *room->getPathList()) 0913 if (!wipePaths.contains(path)) 0914 wipePaths.push_back(path); 0915 // Delete any paths connecting with this room 0916 foreach (CMapPath *path, *room->getConnectingPathList()) 0917 if (!wipePaths.contains(path)) 0918 wipePaths.push_back(path); 0919 foreach (CMapPath *path, wipePaths) 0920 deleteElementWithoutGroup(path,false); 0921 } 0922 0923 if (element->getElementType() == ZONE) 0924 { 0925 // Delete the levels in the zone 0926 CMapZone *zone = (CMapZone *)element; 0927 QList<CMapLevel *> levels; 0928 for (unsigned int idx = 0; idx < zone->levelCount(); ++idx) 0929 levels.append(zone->getLevel(idx)); 0930 foreach (CMapLevel *level, levels) 0931 deleteLevel(level); 0932 } 0933 0934 deleteElementWithoutGroup(element,delOpsite); 0935 0936 closeCommandGroup(); 0937 } 0938 0939 bool CMapManager::isClean() const 0940 { 0941 return commandHistory->isClean(); 0942 } 0943 0944 /** Used to load a map */ 0945 void CMapManager::importMap(const QString& file,CMapFileFilterBase *filter) 0946 { 0947 QFile f(file); 0948 0949 setUndoActive(false); 0950 commandHistory->clear(); 0951 historyGroup = nullptr; 0952 0953 eraseMap(); 0954 0955 if (!f.exists()) 0956 createNewMap(); 0957 else { 0958 // Load the map using the correct filter 0959 filter->loadData(file); 0960 } 0961 0962 if (!getLoginRoom()) 0963 { 0964 CMapRoom *firstRoom = findFirstRoom(nullptr); 0965 setLoginRoom(firstRoom); 0966 } 0967 0968 setCurrentRoomWithoutUndo(loginRoom); 0969 0970 if (loginRoom && activeView) 0971 { 0972 if (activeView->getCurrentlyViewedLevel()==nullptr) 0973 activeView->showPosition(loginRoom,true); 0974 setCurrentRoom(loginRoom); 0975 } 0976 0977 setUndoActive(true); 0978 } 0979 0980 /** Used to save a map */ 0981 void CMapManager::exportMap(const QString& url,CMapFileFilterBase *filter) 0982 { 0983 filter->saveData(url); 0984 commandHistory->setClean(); 0985 } 0986 0987 /** Used to inform to change the state of the navigation tools */ 0988 void CMapManager::activeViewChanged(void) 0989 { 0990 if (!activeView) return; 0991 CMapLevel *level = activeView->getCurrentlyViewedLevel(); 0992 if (!level) return; 0993 0994 // nothing here at this time 0995 } 0996 0997 void CMapManager::levelChanged(CMapLevel *level) 0998 { 0999 if (level==nullptr) 1000 return; 1001 1002 activeView->changedLevel(level); 1003 } 1004 1005 /** Used to inform the various parts of the mapper that a element has changed */ 1006 void CMapManager::changedElement(CMapElement *element) 1007 { 1008 if (element==nullptr) 1009 return; 1010 if (!activeView) return; 1011 1012 for (CMapPluginBase *plugin : pluginList) 1013 plugin->elementChanged(element); 1014 1015 activeView->changedElement(element); 1016 } 1017 1018 /** Used to inform the various parts of the mapper that a element has added */ 1019 void CMapManager::addedElement(CMapElement *element) 1020 { 1021 if (!activeView) return; 1022 if (activeView->getCurrentlyViewedLevel()) 1023 activeView->addedElement(element); 1024 } 1025 1026 1027 /** Used to alter the path properties */ 1028 bool CMapManager::propertiesPath(CMapPath *path) 1029 { 1030 DlgMapPathProperties d(this,path); 1031 1032 return d.exec(); 1033 } 1034 1035 /** Used to alter the room properties */ 1036 bool CMapManager::propertiesRoom(CMapRoom *room) 1037 { 1038 openCommandGroup("Change room properties"); 1039 DlgMapRoomProperties d(this,room); 1040 1041 bool b = d.exec(); 1042 1043 closeCommandGroup(); 1044 1045 return b; 1046 } 1047 1048 /** Used to alter the text properties */ 1049 bool CMapManager::propertiesText(CMapText *text) 1050 { 1051 DlgMapTextProperties d(this,text); 1052 1053 if (d.exec()) 1054 { 1055 text->updateLinkElements(); 1056 return true; 1057 } 1058 1059 return false; 1060 } 1061 1062 void CMapManager::setDefaultOptions() 1063 { 1064 cGlobalSettings *gs = cGlobalSettings::self(); 1065 // directions 1066 gs->setDefaultString ("mapper-direction-north", "north"); 1067 gs->setDefaultString ("mapper-direction-northeast", "northeast"); 1068 gs->setDefaultString ("mapper-direction-east", "east"); 1069 gs->setDefaultString ("mapper-direction-southeast", "southeast"); 1070 gs->setDefaultString ("mapper-direction-south", "south"); 1071 gs->setDefaultString ("mapper-direction-southwest", "southwest"); 1072 gs->setDefaultString ("mapper-direction-west", "west"); 1073 gs->setDefaultString ("mapper-direction-northwest", "northwest"); 1074 gs->setDefaultString ("mapper-direction-up", "up"); 1075 gs->setDefaultString ("mapper-direction-down", "down"); 1076 gs->setDefaultString ("mapper-direction-n", "n"); 1077 gs->setDefaultString ("mapper-direction-ne", "ne"); 1078 gs->setDefaultString ("mapper-direction-e", "e"); 1079 gs->setDefaultString ("mapper-direction-se", "se"); 1080 gs->setDefaultString ("mapper-direction-s", "s"); 1081 gs->setDefaultString ("mapper-direction-sw", "sw"); 1082 gs->setDefaultString ("mapper-direction-w", "w"); 1083 gs->setDefaultString ("mapper-direction-nw", "nw"); 1084 gs->setDefaultString ("mapper-direction-u", "u"); 1085 gs->setDefaultString ("mapper-direction-d", "d"); 1086 1087 // move check 1088 gs->setDefaultBool ("mapper-movement-validcheck", false); 1089 1090 gs->setDefaultColor ("mapper-color-Background", QColor(12*16,12*16,12*16)); 1091 gs->setDefaultColor ("mapper-color-Grid",QColor(160,160,160)); 1092 gs->setDefaultColor ("mapper-color-LowerRoom", Qt::darkGray); 1093 gs->setDefaultColor ("mapper-color-LowerZone", Qt::darkGray); 1094 gs->setDefaultColor ("mapper-color-LowerText", Qt::darkGray); 1095 gs->setDefaultColor ("mapper-color-DefaultRoom", QColor(32,255,0)); 1096 gs->setDefaultColor ("mapper-color-DefaultZone", QColor(32,255,0)); 1097 gs->setDefaultColor ("mapper-color-HigherRoom", Qt::white); 1098 gs->setDefaultColor ("mapper-color-HigherZone", Qt::white); 1099 gs->setDefaultColor ("mapper-color-HigherText", Qt::white); 1100 gs->setDefaultColor ("mapper-color-LowerPath", Qt::darkGray); 1101 gs->setDefaultColor ("mapper-color-DefaultPath", Qt::black); 1102 gs->setDefaultColor ("mapper-color-HigherPath", Qt::white); 1103 gs->setDefaultColor ("mapper-color-DefaultText", Qt::black); 1104 gs->setDefaultColor ("mapper-color-Selected", Qt::blue); 1105 gs->setDefaultColor ("mapper-color-Special", Qt::yellow); 1106 gs->setDefaultColor ("mapper-color-Login", Qt::blue); 1107 gs->setDefaultColor ("mapper-color-Edit", Qt::red); 1108 gs->setDefaultColor ("mapper-color-Current", Qt::red); 1109 1110 // read speedwalk options 1111 gs->setDefaultBool ("mapper-speedwalk-abort-active", true); 1112 gs->setDefaultInt ("mapper-speedwalk-abort-limit", 100); 1113 gs->setDefaultInt ("mapper-speedwalk-delay", 0); 1114 1115 1116 } 1117 1118 /** Used to read the map options */ 1119 void CMapManager::readOptions() 1120 { 1121 cGlobalSettings *gs = cGlobalSettings::self(); 1122 1123 // Read directions 1124 getMapData()->directions[NORTH] = gs->getString ("mapper-direction-north"); 1125 getMapData()->directions[NORTHEAST] = gs->getString ("mapper-direction-northeast"); 1126 getMapData()->directions[EAST] = gs->getString ("mapper-direction-east"); 1127 getMapData()->directions[SOUTHEAST] = gs->getString ("mapper-direction-southeast"); 1128 getMapData()->directions[SOUTH] = gs->getString ("mapper-direction-south"); 1129 getMapData()->directions[SOUTHWEST] = gs->getString ("mapper-direction-southwest"); 1130 getMapData()->directions[WEST] = gs->getString ("mapper-direction-west"); 1131 getMapData()->directions[NORTHWEST] = gs->getString ("mapper-direction-northwest"); 1132 getMapData()->directions[UP] = gs->getString ("mapper-direction-up"); 1133 getMapData()->directions[DOWN] = gs->getString ("mapper-direction-down"); 1134 1135 int half = NUM_DIRECTIONS/2; 1136 getMapData()->directions[NORTH+half] = gs->getString ("mapper-direction-n"); 1137 getMapData()->directions[NORTHEAST+half] = gs->getString ("mapper-direction-ne"); 1138 getMapData()->directions[EAST+half] = gs->getString ("mapper-direction-e"); 1139 getMapData()->directions[SOUTHEAST+half] = gs->getString ("mapper-direction-se"); 1140 getMapData()->directions[SOUTH+half] = gs->getString ("mapper-direction-s"); 1141 getMapData()->directions[SOUTHWEST+half] = gs->getString ("mapper-direction-sw"); 1142 getMapData()->directions[WEST+half] = gs->getString ("mapper-direction-w"); 1143 getMapData()->directions[NORTHWEST+half] = gs->getString ("mapper-direction-nw"); 1144 getMapData()->directions[UP+half] = gs->getString ("mapper-direction-u"); 1145 getMapData()->directions[DOWN+half] = gs->getString ("mapper-direction-d"); 1146 1147 // Read movecheck config 1148 getMapData()->validRoomCheck = gs->getBool ("mapper-movement-validcheck"); 1149 int count = gs->getInt ("mapper-movement-check-count"); 1150 getMapData()->failedMoveMsg.clear(); 1151 for (int i = 1; i <= count; ++i) 1152 getMapData()->failedMoveMsg << gs->getString ("mapper-movement-check-" + QString::number (i)); 1153 1154 // Read map colors 1155 mapData->backgroundColor=gs->getColor ("mapper-color-Background"); 1156 mapData->gridColor=gs->getColor ("mapper-color-Grid"); 1157 mapData->lowerRoomColor=gs->getColor ("mapper-color-LowerRoom"); 1158 mapData->lowerZoneColor=gs->getColor ("mapper-color-LowerZone"); 1159 mapData->lowerTextColor=gs->getColor ("mapper-color-LowerText"); 1160 mapData->defaultRoomColor=gs->getColor ("mapper-color-DefaultRoom"); 1161 mapData->defaultZoneColor=gs->getColor ("mapper-color-DefaultZone"); 1162 mapData->higherRoomColor=gs->getColor ("mapper-color-HigherRoom"); 1163 mapData->higherZoneColor=gs->getColor ("mapper-color-HigherZone"); 1164 mapData->higherTextColor=gs->getColor ("mapper-color-HigherText"); 1165 mapData->lowerPathColor=gs->getColor ("mapper-color-LowerPath"); 1166 mapData->defaultPathColor=gs->getColor ("mapper-color-DefaultPath"); 1167 mapData->higherPathColor=gs->getColor ("mapper-color-HigherPath"); 1168 mapData->defaultTextColor=gs->getColor ("mapper-color-DefaultText"); 1169 mapData->selectedColor=gs->getColor ("mapper-color-Selected"); 1170 mapData->specialColor = gs->getColor ("mapper-color-Special"); 1171 mapData->loginColor=gs->getColor ("mapper-color-Login"); 1172 mapData->editColor=gs->getColor ("mapper-color-Edit"); 1173 mapData->currentColor=gs->getColor ("mapper-color-Current"); 1174 1175 // read speedwalk options 1176 mapData->speedwalkAbortActive = gs->getBool ("mapper-speedwalk-abort-active"); 1177 mapData->speedwalkAbortLimit = gs->getInt ("mapper-speedwalk-abort-limit"); 1178 mapData->speedwalkDelay = gs->getInt ("mapper-speedwalk-delay"); 1179 1180 activeView->readOptions(); 1181 1182 for (CMapPluginBase *plugin : pluginList) 1183 plugin->loadConfigOptions(); 1184 } 1185 1186 /** Used to write the map options */ 1187 void CMapManager::saveGlobalConfig() 1188 { 1189 cGlobalSettings *gs = cGlobalSettings::self(); 1190 1191 // directions 1192 gs->setString ("mapper-direction-north", getMapData()->directions[NORTH]); 1193 gs->setString ("mapper-direction-northeast", getMapData()->directions[NORTHEAST]); 1194 gs->setString ("mapper-direction-east", getMapData()->directions[EAST]); 1195 gs->setString ("mapper-direction-southeast", getMapData()->directions[SOUTHEAST]); 1196 gs->setString ("mapper-direction-south", getMapData()->directions[SOUTH]); 1197 gs->setString ("mapper-direction-southeast", getMapData()->directions[SOUTHWEST]); 1198 gs->setString ("mapper-direction-west", getMapData()->directions[WEST]); 1199 gs->setString ("mapper-direction-northwest", getMapData()->directions[NORTHWEST]); 1200 gs->setString ("mapper-direction-up", getMapData()->directions[UP]); 1201 gs->setString ("mapper-direction-down", getMapData()->directions[DOWN]); 1202 1203 int half = NUM_DIRECTIONS/2; 1204 gs->setString ("mapper-direction-n", getMapData()->directions[NORTH+half]); 1205 gs->setString ("mapper-direction-ne", getMapData()->directions[NORTHEAST+half]); 1206 gs->setString ("mapper-direction-e", getMapData()->directions[EAST+half]); 1207 gs->setString ("mapper-direction-se", getMapData()->directions[SOUTHEAST+half]); 1208 gs->setString ("mapper-direction-s", getMapData()->directions[SOUTH+half]); 1209 gs->setString ("mapper-direction-sw", getMapData()->directions[SOUTHWEST+half]); 1210 gs->setString ("mapper-direction-w", getMapData()->directions[WEST+half]); 1211 gs->setString ("mapper-direction-nw", getMapData()->directions[NORTHWEST+half]); 1212 gs->setString ("mapper-direction-u", getMapData()->directions[UP+half]); 1213 gs->setString ("mapper-direction-d", getMapData()->directions[DOWN+half]); 1214 1215 // movement 1216 gs->setBool ("mapper-movement-validcheck", getMapData()->validRoomCheck); 1217 gs->setInt ("mapper-movement-check-count", getMapData()->failedMoveMsg.size()); 1218 int idx = 0; 1219 QStringList::iterator it; 1220 for (it = getMapData()->failedMoveMsg.begin(); it != getMapData()->failedMoveMsg.end(); ++it) 1221 gs->setString ("mapper-movement-check-" + QString::number (++idx), *it); 1222 1223 gs->setColor ("mapper-color-Background", mapData->backgroundColor); 1224 gs->setColor ("mapper-color-Grid", mapData->gridColor); 1225 gs->setColor ("mapper-color-LowerRoom", mapData->lowerRoomColor); 1226 gs->setColor ("mapper-color-LowerZone", mapData->lowerZoneColor); 1227 gs->setColor ("mapper-color-LowerText", mapData->lowerTextColor); 1228 gs->setColor ("mapper-color-HigherZone", mapData->higherZoneColor); 1229 gs->setColor ("mapper-color-DefaultRoom", mapData->defaultRoomColor); 1230 gs->setColor ("mapper-color-DefaultZone", mapData->defaultZoneColor); 1231 gs->setColor ("mapper-color-DefaultText", mapData->defaultTextColor); 1232 gs->setColor ("mapper-color-HigherRoom", mapData->higherRoomColor); 1233 gs->setColor ("mapper-color-HigherText", mapData->higherTextColor); 1234 gs->setColor ("mapper-color-LowerPath", mapData->lowerPathColor); 1235 gs->setColor ("mapper-color-DefaultPath",mapData->defaultPathColor); 1236 gs->setColor ("mapper-color-HigherPath", mapData->higherPathColor); 1237 gs->setColor ("mapper-color-Selected", mapData->selectedColor); 1238 gs->setColor ("mapper-color-Special", mapData->specialColor); 1239 gs->setColor ("mapper-color-Login", mapData->loginColor); 1240 gs->setColor ("mapper-color-Edit", mapData->editColor); 1241 gs->setColor ("mapper-color-Current", mapData->currentColor); 1242 1243 for (CMapPluginBase *plugin : pluginList) 1244 plugin->saveConfigOptions(); 1245 1246 gs->setBool ("mapper-speedwalk-abort-active", mapData->speedwalkAbortActive); 1247 gs->setInt ("mapper-speedwalk-abort-limit", mapData->speedwalkAbortLimit); 1248 gs->setInt ("mapper-speedwalk-delay", mapData->speedwalkDelay); 1249 1250 redrawAllViews(); 1251 } 1252 1253 void CMapManager::getCounts(int *levels,int *rooms,int *paths,int *labels) 1254 { 1255 *rooms = 0; 1256 *labels = 0; 1257 *paths = 0; 1258 CMapZone *zone = getZone(); 1259 *levels = zone->levelCount(); 1260 1261 for (unsigned int idx = 0; idx < zone->levelCount(); ++idx) 1262 { 1263 CMapLevel *level = zone->getLevel(idx); 1264 1265 foreach (CMapRoom *room, *level->getRoomList()) 1266 *paths += room->getPathList()->count(); 1267 1268 *rooms += level->getRoomList()->count(); 1269 *labels += level->getTextList()->count(); 1270 } 1271 } 1272 1273 directionTyp CMapManager::getOpsiteDirection(directionTyp dir) 1274 { 1275 directionTyp result = SOUTH; 1276 switch (dir) 1277 { 1278 case NORTH : result = SOUTH; break; 1279 case SOUTH : result = NORTH; break; 1280 case EAST : result = WEST; break; 1281 case WEST : result = EAST; break; 1282 case NORTHWEST : result = SOUTHEAST; break; 1283 case NORTHEAST : result = SOUTHWEST; break; 1284 case SOUTHWEST : result = NORTHEAST; break; 1285 case SOUTHEAST : result = NORTHWEST; break; 1286 case UP : result = DOWN; break; 1287 case DOWN : result = UP; break; 1288 case SPECIAL : result = SPECIAL; break; 1289 } 1290 1291 return result; 1292 } 1293 1294 /** Used to set the current tool */ 1295 void CMapManager::setCurrentTool(CMapToolBase *tool) 1296 { 1297 if (currentTool) 1298 currentTool->toolUnselected(); 1299 1300 currentTool=tool; 1301 1302 if (currentTool) 1303 currentTool->toolSelected(); 1304 1305 activeView->changed(); 1306 } 1307 1308 /** Usd to get the current tool */ 1309 CMapToolBase *CMapManager::getCurrentTool(void) 1310 { 1311 return currentTool; 1312 } 1313 1314 /** This method puts a element into edit state */ 1315 void CMapManager::setEditElement(CMapElement *element) 1316 { 1317 if (elementEdit) 1318 { 1319 elementEdit->setEditMode(false); 1320 changedElement(elementEdit); 1321 } 1322 1323 element->setEditMode(true); 1324 elementEdit = element; 1325 changedElement(elementEdit); 1326 } 1327 1328 /** This is used to remove edit state from element being edited */ 1329 void CMapManager::unsetEditElement(void) 1330 { 1331 if (elementEdit) 1332 { 1333 elementEdit->setEditMode(false); 1334 changedElement(elementEdit); 1335 } 1336 } 1337 1338 /** This gets the element that is being edited */ 1339 CMapElement *CMapManager::getEditElement(void) 1340 { 1341 return elementEdit; 1342 } 1343 1344 /** This cancels any editing */ 1345 void CMapManager::stopEditing(void) 1346 { 1347 if (elementEdit) 1348 { 1349 elementEdit->setEditMode(false); 1350 } 1351 1352 elementEdit = nullptr; 1353 } 1354 1355 int CMapManager::getUndoActive(void) 1356 { 1357 return m_commandsActive; 1358 } 1359 1360 /** This is used to tell the mapper if commands should be added to the history list */ 1361 void CMapManager::setUndoActive(bool active) 1362 { 1363 m_commandsActive = active; 1364 } 1365 1366 /** Used to add a command to the command history */ 1367 void CMapManager::addCommand(CMapCommand *command) 1368 { 1369 if (getUndoActive()) 1370 { 1371 if (historyGroup) 1372 { 1373 // If there is a history group, it will -not- execute anything. That will happen once the group gets closed. 1374 historyGroup->addCommand(command); 1375 } 1376 else 1377 { 1378 commandHistory->push(command); 1379 } 1380 } 1381 else 1382 { 1383 command->redo(); 1384 } 1385 } 1386 1387 void CMapManager::openCommandGroup(QString name) 1388 { 1389 CMapCmdGroup *group = new CMapCmdGroup(this,name); 1390 group->setPreviousGroup(historyGroup); 1391 historyGroup = group; 1392 } 1393 1394 void CMapManager::closeCommandGroup() 1395 { 1396 CMapCmdGroup *currentGroup = historyGroup; 1397 CMapCmdGroup *oldGroup =historyGroup->getPreviousGroup(); 1398 historyGroup = oldGroup; 1399 addCommand(currentGroup); 1400 } 1401 1402 /** move the player relative to the current position of the player 1403 * @param cmd The move command used to move the player */ 1404 void CMapManager::movePlayerBy(QString cmd) 1405 { 1406 QString specialCmd = ""; 1407 directionTyp dir = textToDirection(cmd); 1408 1409 if (dir == SPECIAL) 1410 specialCmd = cmd; 1411 1412 movePlayerBy(dir, getActiveView()->getCreateMode(), specialCmd); 1413 } 1414 1415 /** move the player relative to the current position of the player 1416 * This command has support for special paths, but can only move 1417 * anlong exsiting special paths. In other words, it is unable to 1418 * create special paths. 1419 */ 1420 void CMapManager::movePlayerBy(directionTyp dir,bool create,QString specialCmd) 1421 { 1422 // Make sure that the room we are currently in is visible 1423 if (!currentRoom) return; 1424 1425 CMapCmdMovePlayer *cmd = new CMapCmdMovePlayer(this, dir, specialCmd, create); 1426 addCommand(cmd); 1427 } 1428 1429 /** Used to walk the player in the mud to a given room */ 1430 void CMapManager::walkPlayerTo(CMapRoom *toRoom) 1431 { 1432 QQueue<CMapRoom *> roomsToVisit; 1433 CMapRoom *destRoom; 1434 CMapRoom *srcRoom; 1435 CMapPath *path; 1436 CMapRoom *foundRoom; 1437 signed int time = 0; 1438 bool bFound = false; 1439 CMapPath *foundPath = nullptr; 1440 1441 int speedWalkAbortCount = 0; 1442 1443 if ((!currentRoom) || (currentRoom == toRoom)) return; 1444 1445 if (speedwalkActive) 1446 { 1447 KMessageBox::information (nullptr,i18n("Speedwalking is already in progress"),i18n("KMuddy Mapper")); 1448 return; 1449 } 1450 1451 speedwalkActive = true; 1452 1453 pathToWalk.clear(); 1454 1455 // Reset the seach count for all the rooms 1456 for (unsigned int idx = 0; idx < getZone()->levelCount(); ++idx) 1457 { 1458 CMapLevel *level = getZone()->getLevel(idx); 1459 foreach (CMapRoom *room, *level->getRoomList()) 1460 room->setMoveTime(-1); 1461 } 1462 1463 // Init things for the start room 1464 srcRoom = currentRoom; 1465 destRoom = (CMapRoom *)toRoom; 1466 srcRoom->setMoveTime(time++); 1467 1468 // enqueue starting room 1469 roomsToVisit.enqueue(srcRoom); 1470 CMapRoom* room; 1471 1472 // this is the Breadth First Search Algorithm 1473 while (!(roomsToVisit.isEmpty() || bFound)) 1474 { 1475 foundRoom = roomsToVisit.dequeue(); 1476 1477 // for all neighbours of foundRoom 1478 foreach (path, *foundRoom->getPathList()) 1479 { 1480 room = path->getDestRoom(); 1481 1482 if (room == destRoom) 1483 { 1484 bFound = true; 1485 break; 1486 } 1487 1488 // neighbour has not been visited yet, enqueue it 1489 if (room->getMoveTime() == -1) 1490 { 1491 room->setMoveTime(time++); 1492 roomsToVisit.enqueue(room); 1493 } 1494 } 1495 } 1496 1497 // Check to see if we were unable to find any paths 1498 if (!bFound) 1499 { 1500 speedwalkActive = false; 1501 KMessageBox::information (nullptr,i18n("The automapper was unable to find a path to requested room"),i18n("KMuddy Mapper")); 1502 return; 1503 } 1504 1505 speedWalkAbortCount=0; 1506 1507 // Trace steps that need to be taken backwards from the dest to the src room 1508 while(destRoom != srcRoom) 1509 { 1510 time = destRoom->getConnectingPathList()->first()->getSrcRoom()->getMoveTime(); 1511 foundRoom = destRoom->getConnectingPathList()->first()->getSrcRoom(); 1512 1513 // Find the room with the shortest time as this is the room we 1514 // should be moving to. 1515 foreach (path, *destRoom->getConnectingPathList()) 1516 { 1517 if (time == -1 || (path->getSrcRoom()->getMoveTime()<=time && path->getSrcRoom()->getMoveTime()!=-1)) 1518 { 1519 time = path->getSrcRoom()->getMoveTime(); 1520 foundRoom = path->getSrcRoom(); 1521 foundPath = path; 1522 } 1523 } 1524 1525 pathToWalk.append(directionToText(foundPath->getSrcDir(),foundPath->getSpecialCmd())); 1526 1527 destRoom=foundRoom; 1528 // Check to make sure that tings are not stuck in a loop and abort 1529 // if the move limit is reached 1530 1531 speedWalkAbortCount++; 1532 if (mapData->speedwalkAbortActive && (speedWalkAbortCount == mapData->speedwalkAbortLimit)) 1533 { 1534 speedwalkActive = false; 1535 KMessageBox::information (nullptr,i18n("Speedwalk abort because move limit was reached"),i18n("KMuddy Mapper")); 1536 1537 return; 1538 } 1539 } 1540 1541 speedwalkProgressDlg->setTotalSteps(pathToWalk.count()); 1542 speedwalkProgressDlg->setProgress(0); 1543 1544 cActionManager *am = cActionManager::self(); 1545 cStatus *status = dynamic_cast<cStatus *>(am->object ("status", am->activeSession())); 1546 if (status) 1547 status->statusBar()->addPermanentWidget(speedwalkProgressDlg,0); 1548 speedwalkProgressDlg->show(); 1549 speedwalkProgress = 0; 1550 1551 // Start walking path 1552 slotWalkPlayerAlongPath(); 1553 } 1554 1555 void CMapManager::slotAbortSpeedwalk(void) 1556 { 1557 pathToWalk.clear(); 1558 speedwalkActive = false; 1559 speedwalkProgressDlg->setProgress(speedwalkProgressDlg->getTotalSteps()); 1560 speedwalkProgressDlg->hide(); 1561 cActionManager *am = cActionManager::self(); 1562 cStatus *status = dynamic_cast<cStatus *>(am->object ("status", am->activeSession())); 1563 if (status) 1564 status->statusBar()->removeWidget(speedwalkProgressDlg); 1565 } 1566 1567 /** Used to recersivly move the play along a speedwalk path */ 1568 void CMapManager::slotWalkPlayerAlongPath(void) 1569 { 1570 if (speedwalkActive) 1571 { 1572 QString dir = pathToWalk.takeFirst(); 1573 1574 // TODO: using active session isn't a very good idea; progress bar should be shown on the mapper window, not in KMuddy's status bar; furthermore, the mapper should distinguish sessions and switch maps when session changes or something - until all this gets done, we cannot implement this any better 1575 mapperPlugin->sendCommand (mapperPlugin->activeSession(), dir); 1576 speedwalkProgressDlg->setProgress(++speedwalkProgress); 1577 1578 // Walk the path 1579 if (!pathToWalk.isEmpty()) 1580 { 1581 QTimer::singleShot( mapData->speedwalkDelay * 100, this, SLOT(slotWalkPlayerAlongPath()) ); 1582 } 1583 else 1584 { 1585 slotAbortSpeedwalk(); 1586 } 1587 } 1588 } 1589 1590 /** This method is used to convert a direction into a offset */ 1591 void CMapManager::directionToCord(directionTyp dir, QSize distance,QPoint *pos) 1592 { 1593 int x = pos->x(); 1594 int y = pos->y(); 1595 1596 switch (dir) 1597 { 1598 case NORTH : x = 0; 1599 y = -distance.height(); 1600 break; 1601 case EAST : x = distance.width(); 1602 y = 0; 1603 break; 1604 case SOUTH : x = 0; 1605 y = distance.height(); 1606 break; 1607 case WEST : x = -distance.width(); 1608 y = 0; 1609 break; 1610 case NORTHEAST : x = distance.width(); 1611 y = -distance.height(); 1612 break; 1613 case NORTHWEST : x = -distance.width(); 1614 y = -distance.height(); 1615 break; 1616 case SOUTHEAST : x = distance.width(); 1617 y = distance.height(); 1618 break; 1619 case SOUTHWEST : x = -distance.width(); 1620 y = distance.height(); 1621 break; 1622 case UP : break; 1623 case DOWN : break; 1624 case SPECIAL : break; 1625 } 1626 1627 pos->setX(x); 1628 pos->setY(y); 1629 } 1630 1631 /** This method is used to move the elements in a zone by the given vector */ 1632 void CMapManager::moveMap(QPoint inc,CMapZone *) 1633 { 1634 CMapCmdMoveMap *cmd = new CMapCmdMoveMap(this,inc,i18n("Move Elements in map")); 1635 addCommand(cmd); 1636 } 1637 1638 /** This method is used to make a path two way */ 1639 void CMapManager::makePathTwoWay(CMapPath *path) 1640 { 1641 if (!path->getOpsitePath()) 1642 { 1643 CMapCmdTogglePathTwoWay *cmd = new CMapCmdTogglePathTwoWay(this,i18n("Make Path Two-Way"),path); 1644 addCommand(cmd); 1645 } 1646 } 1647 1648 /** This method is used to make a path one way */ 1649 void CMapManager::makePathOneWay(CMapPath *path) 1650 { 1651 if (path->getOpsitePath()) 1652 { 1653 CMapCmdTogglePathTwoWay *cmd = new CMapCmdTogglePathTwoWay(this,i18n("Make Path One-Way"),path); 1654 addCommand(cmd); 1655 } 1656 } 1657 1658 /** Get the main window */ 1659 CMapView *CMapManager::getActiveView() 1660 { 1661 return activeView; 1662 } 1663 1664 /** Used to repaint all the views */ 1665 void CMapManager::redrawAllViews(void) 1666 { 1667 activeView->changed(); 1668 } 1669 1670 CMapFileFilterBase *CMapManager::nativeFilter(bool isLoad) 1671 { 1672 for (CMapFileFilterBase *filter : m_fileFilter) 1673 { 1674 if (isLoad && (!filter->supportLoad())) continue; 1675 if ((!isLoad) && (!filter->supportSave())) continue; 1676 if (filter->isNative()) return filter; 1677 } 1678 return nullptr; 1679 } 1680 1681 QString CMapManager::defaultSavePath () const 1682 { 1683 return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/maps/"; 1684 } 1685 1686 /** This is a debug function and not for genreal use */ 1687 void CMapManager::changeProperties(CMapElement *element,QString key,QString oldData,QString newData) 1688 { 1689 CMapCmdElementProperties *cmd = new CMapCmdElementProperties(this,i18n("Change Element Property"),element); 1690 cmd->getOrgProperties().writeEntry(key,oldData); 1691 cmd->getNewProperties().writeEntry(key,newData); 1692 addCommand(cmd); 1693 } 1694 1695 /** This is a debug function and not for genreal use */ 1696 void CMapManager::changeProperties(CMapElement *element,QString key,int oldData,int newData) 1697 { 1698 CMapCmdElementProperties *cmd = new CMapCmdElementProperties(this,i18n("Change Element Property"),element); 1699 cmd->getOrgProperties().writeEntry(key,oldData); 1700 cmd->getNewProperties().writeEntry(key,newData); 1701 addCommand(cmd); 1702 } 1703 1704 /** This is a debug function and not for genreal use */ 1705 void CMapManager::generateTestMap() 1706 { 1707 qDebug() << "creating test map"; 1708 bool smallMap = false; 1709 1710 ///////////////////////////////////////////////////////////////////// 1711 // Create a new empty map 1712 setUndoActive(false); 1713 commandHistory->clear(); 1714 historyGroup = nullptr; 1715 eraseMap(); 1716 createNewMap(); 1717 setUndoActive(true); 1718 1719 ///////////////////////////////////////////////////////////////////// 1720 // Create a test map 1721 // Test rooms and paths 1722 1723 openCommandGroup("Create Test Map"); 1724 1725 if (!smallMap) 1726 { 1727 movePlayerBy(SOUTH,true,""); 1728 movePlayerBy(SOUTH,true,""); 1729 movePlayerBy(SOUTH,true,""); 1730 movePlayerBy(WEST,true,""); 1731 movePlayerBy(NORTH,true,""); 1732 movePlayerBy(EAST,true,""); 1733 movePlayerBy(EAST,true,""); 1734 movePlayerBy(SOUTH,true,""); 1735 movePlayerBy(SOUTH,true,""); 1736 movePlayerBy(SOUTH,true,""); 1737 movePlayerBy(EAST,true,""); 1738 movePlayerBy(EAST,true,""); 1739 movePlayerBy(EAST,true,""); 1740 movePlayerBy(EAST,true,""); 1741 1742 movePlayerBy(UP,true,""); 1743 movePlayerBy(EAST,true,""); 1744 movePlayerBy(EAST,true,""); 1745 movePlayerBy(EAST,true,""); 1746 movePlayerBy(EAST,true,""); 1747 movePlayerBy(SOUTH,true,""); 1748 movePlayerBy(SOUTH,true,""); 1749 movePlayerBy(SOUTH,true,""); 1750 movePlayerBy(SOUTH,true,""); 1751 movePlayerBy(SOUTH,true,""); 1752 movePlayerBy(SOUTH,true,""); 1753 movePlayerBy(EAST,true,""); 1754 movePlayerBy(EAST,true,""); 1755 movePlayerBy(DOWN,true,""); 1756 1757 movePlayerBy(DOWN,true,""); 1758 movePlayerBy(SOUTH,true,""); 1759 movePlayerBy(SOUTH,true,""); 1760 movePlayerBy(SOUTH,true,""); 1761 movePlayerBy(SOUTH,true,""); 1762 movePlayerBy(SOUTH,true,""); 1763 movePlayerBy(EAST,true,""); 1764 movePlayerBy(EAST,true,""); 1765 movePlayerBy(UP,true,""); 1766 1767 movePlayerBy(SOUTH,true,""); 1768 movePlayerBy(WEST,true,""); 1769 1770 // Test text 1771 changeProperties(getZone(),"Label","",i18n("Root Zone")); 1772 1773 } 1774 1775 CMapLevel *level = getZone()->firstLevel(); 1776 if (level->getNextLevel()) 1777 level = level->getNextLevel(); 1778 1779 QFont font = QFont("times"); 1780 font.setPointSize(25); 1781 createText(QPoint(160,20),level,"Test Map",font,Qt::black); 1782 1783 1784 if (!smallMap) 1785 { 1786 CMapRoom *test1=CMapElementUtil::createRoom(this, QPoint(14*20,14*20),level); 1787 changeProperties(test1,"Label","",i18n("Test room 1")); 1788 changeProperties(test1,"LabelPos",(int)CMapRoom::HIDE,(int)CMapRoom::WEST); 1789 CMapRoom *test2=CMapElementUtil::createRoom(this, QPoint(20*20,20*20),level); 1790 changeProperties(test2,"Label","",i18n("Test room 2")); 1791 changeProperties(test2,"LabelPos",(int)CMapRoom::HIDE,(int)CMapRoom::EAST); 1792 CMapRoom *test3=CMapElementUtil::createRoom(this, QPoint(14*20,20*20),level); 1793 changeProperties(test3,"Label","",i18n("Test room 3")); 1794 changeProperties(test3,"LabelPos",(int)CMapRoom::HIDE,(int)CMapRoom::WEST); 1795 CMapRoom *test4=CMapElementUtil::createRoom(this, QPoint(20*20,14*20),level); 1796 changeProperties(test4,"Label","",i18n("Test room 4")); 1797 changeProperties(test4,"LabelPos",(int)CMapRoom::HIDE,(int)CMapRoom::NORTH); 1798 1799 createPath(QPoint(14*20,14*20),level,SOUTHEAST, 1800 QPoint(20*20,20*20),level,NORTHWEST); 1801 createPath(QPoint(20*20,20*20),level,NORTHWEST, 1802 QPoint(14*20,14*20),level,SOUTHEAST); 1803 createPath(QPoint(14*20,20*20),level,NORTHEAST, 1804 QPoint(20*20,14*20),level,SOUTHWEST); 1805 1806 createPath(QPoint(20*20,14*20),level,SOUTHWEST, 1807 QPoint(14*20,20*20),level,NORTHEAST); 1808 1809 CMapPath *specialPath = createPath(test1,SPECIAL,test4,SPECIAL); 1810 makePathTwoWay(specialPath); 1811 1812 CMapCmdElementProperties *cmd = new CMapCmdElementProperties(this,i18n("Set Special Exit"),specialPath); 1813 cmd->getOrgProperties().writeEntry("SpecialCmdSrc",""); 1814 cmd->getOrgProperties().writeEntry("SpecialCmdDest",""); 1815 cmd->getOrgProperties().writeEntry("SpecialExit",false); 1816 cmd->getNewProperties().writeEntry("SpecialCmdSrc","enter"); 1817 cmd->getNewProperties().writeEntry("SpecialCmdDest","out"); 1818 cmd->getNewProperties().writeEntry("SpecialExit",true); 1819 addCommand(cmd); 1820 } 1821 closeCommandGroup(); 1822 qDebug() << "test map created"; 1823 } 1824 1825 #include "moc_cmapmanager.cpp"