File indexing completed on 2023-09-24 04:17:27
0001 /*************************************************************************** 0002 cmapclipboard.cpp 0003 ------------------- 0004 begin : Wed Jul 3 2002 0005 copyright : (C) 2002 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 "cmapclipboard.h" 0019 0020 #include <kactioncollection.h> 0021 #include <kdebug.h> 0022 #include <klocale.h> 0023 0024 #include <QAction> 0025 0026 #include "cmapmanager.h" 0027 #include "cmappath.h" 0028 #include "cmapzone.h" 0029 #include "cmaptext.h" 0030 #include "cmaproom.h" 0031 #include "cmaplevel.h" 0032 #include "cmapview.h" 0033 #include "cmapcmdelementcreate.h" 0034 #include "cmapcmdelementproperties.h" 0035 0036 #include "kmemconfig.h" 0037 0038 CMapClipboard::CMapClipboard(CMapManager *mapManager, CMapView *view, QObject *parent) : 0039 QObject(parent), 0040 m_mapManager(mapManager), 0041 m_view(view), 0042 m_parent(parent) 0043 { 0044 kDebug() << "CMapClipboard::CMapClipboard constructor begins"; 0045 0046 m_clipboard = nullptr; 0047 initActions(); 0048 kDebug() << "CMapClipboard::CMapClipboard constructor ends"; 0049 } 0050 0051 CMapClipboard::~CMapClipboard() 0052 { 0053 if (m_clipboard) 0054 delete m_clipboard; 0055 } 0056 0057 /** This is used to create the clipboard actions */ 0058 void CMapClipboard::initActions(void) 0059 { 0060 // Edit menu 0061 KActionCollection *acol = m_view->actionCollection(); 0062 0063 m_editSelectAll = new QAction (m_parent); 0064 m_editSelectAll->setText (i18n ("Select All")); 0065 connect (m_editSelectAll, SIGNAL (triggered ()), this, SLOT (slotSelectAll ())); 0066 acol->addAction ("editSelectAll", m_editSelectAll); 0067 m_editUnselectAll = new QAction (m_parent); 0068 m_editUnselectAll->setText (i18n ("Unselect All")); 0069 connect (m_editUnselectAll, SIGNAL (triggered ()), this, SLOT (slotUnselectAll ())); 0070 acol->addAction ("editUnselectAll", m_editUnselectAll); 0071 m_editSelectInvert = new QAction (m_parent); 0072 m_editSelectInvert->setText (i18n ("Invert Selection")); 0073 connect (m_editSelectInvert, SIGNAL (triggered ()), this, SLOT (slotInvertSelection ())); 0074 acol->addAction ("editSelectInvert", m_editSelectInvert); 0075 m_editDelete = new QAction (m_parent); 0076 m_editDelete->setText (i18n ("Delete")); 0077 connect (m_editDelete, SIGNAL (triggered ()), this, SLOT (slotDelete ())); 0078 acol->addAction ("editDelete", m_editDelete); 0079 m_editCopy = new QAction (m_parent); 0080 m_editCopy->setText (i18n ("Copy")); 0081 connect (m_editCopy, SIGNAL (triggered ()), this, SLOT (slotCopy ())); 0082 acol->addAction ("editCopy", m_editCopy); 0083 m_editCut = new QAction (m_parent); 0084 m_editCut->setText (i18n ("Cut")); 0085 connect (m_editCut, SIGNAL (triggered ()), this, SLOT (slotCut ())); 0086 acol->addAction ("editCut", m_editCut); 0087 m_editPaste = new QAction (m_parent); 0088 m_editPaste->setText (i18n ("Paste")); 0089 connect (m_editPaste, SIGNAL (triggered ()), this, SLOT (slotPaste ())); 0090 acol->addAction ("editPaste", m_editPaste); 0091 } 0092 0093 /** This method is used to set the enabled start of the actions */ 0094 void CMapClipboard::enableActions(bool enabled) 0095 { 0096 m_editSelectAll->setEnabled(enabled); 0097 m_editUnselectAll->setEnabled(enabled); 0098 m_editSelectInvert->setEnabled(enabled); 0099 m_editDelete->setEnabled(enabled); 0100 m_editCopy->setEnabled(enabled); 0101 m_editCut->setEnabled(enabled); 0102 m_editPaste->setEnabled(enabled); 0103 } 0104 0105 /** This method is called to copy the selected elements into the clipboard */ 0106 void CMapClipboard::slotCopy() 0107 { 0108 if (m_clipboard) 0109 delete m_clipboard; 0110 0111 m_clipboard = new KMemConfig(); 0112 0113 if (m_mapManager->getActiveView()) 0114 { 0115 int group = 0; 0116 // Copy all the elements except for paths that are selected 0117 CMapLevel *level = m_mapManager->getActiveView()->getCurrentlyViewedLevel(); 0118 QList<CMapElement *> lst = level->getAllElements(); 0119 foreach (CMapElement *element, lst) 0120 { 0121 if (!element->getSelected()) continue; 0122 group++; 0123 QString grp; 0124 grp.sprintf("%d",group); 0125 KConfigGroup clipGroup = m_clipboard->group(grp); 0126 0127 switch (element->getElementType()) 0128 { 0129 case ROOM : { 0130 CMapRoom *room = (CMapRoom *)element; 0131 room->saveProperties(clipGroup); 0132 clipGroup.deleteEntry("RoomID"); 0133 clipGroup.writeEntry("LabelPos",(int)CMapRoom::HIDE); 0134 } 0135 break; 0136 case TEXT : if (!((CMapText *)element)->getLinkElement()) 0137 { 0138 element->saveProperties(clipGroup); 0139 clipGroup.deleteEntry("TextID"); 0140 } 0141 break; 0142 default : break; 0143 } 0144 } 0145 0146 // Copy all the path elements into the clipboard 0147 int pathGroup = 0; 0148 0149 for (unsigned int idx = 0; idx < m_mapManager->getZone()->levelCount(); ++idx) 0150 { 0151 CMapLevel *level = m_mapManager->getZone()->getLevel(idx); 0152 0153 foreach (CMapRoom *room, *level->getRoomList()) 0154 { 0155 foreach (CMapPath *path, *room->getPathList()) 0156 { 0157 if ((path->getSrcRoom()->getSelected() || path->getSrcRoom()->getZone()->getSelected()) && 0158 (path->getDestRoom()->getSelected() || path->getDestRoom()->getZone()->getSelected())) 0159 { 0160 copyPath (&pathGroup,path); 0161 } 0162 } 0163 } 0164 } 0165 0166 // Copy all the linked text elements 0167 int linkGroup =0; 0168 0169 foreach (CMapElement *element, lst) 0170 { 0171 if (element->getSelected() && element->getElementType()==TEXT) 0172 { 0173 CMapText *text = (CMapText *)element; 0174 CMapElement *link = text->getLinkElement(); 0175 if (link) 0176 { 0177 linkGroup++; 0178 QString grp; 0179 grp.sprintf("LINK%d",linkGroup); 0180 KConfigGroup clipGroup = m_clipboard->group(grp); 0181 0182 text->saveProperties(clipGroup); 0183 0184 clipGroup.writeEntry("LinkLevelNum",link->getLevel()->getNumber()); 0185 0186 clipGroup.writeEntry("LinkX",link->getX()); 0187 clipGroup.writeEntry("LinkY",link->getY()); 0188 clipGroup.writeEntry("LinkZone",link->getZone()->getZoneID()); 0189 } 0190 } 0191 } 0192 0193 // Copy the selected paths 0194 KConfigGroup header = m_clipboard->group("Header"); 0195 header.writeEntry("Elements",group); 0196 header.writeEntry("Paths",pathGroup); 0197 header.writeEntry("Links",linkGroup); 0198 } 0199 } 0200 0201 /** This method is used to copy a path into the clipboard */ 0202 void CMapClipboard::copyPath(int *pathGroup,CMapPath *path) 0203 { 0204 (*pathGroup)++; 0205 QString grp; 0206 grp.sprintf("PATH%d",*pathGroup); 0207 KConfigGroup pGroup = m_clipboard->group(grp); 0208 0209 path->saveProperties(pGroup); 0210 pGroup.writeEntry("SrcLevelNum",path->getSrcRoom()->getLevel()->getNumber()); 0211 pGroup.writeEntry("DestLevelNum",path->getDestRoom()->getLevel()->getNumber()); 0212 pGroup.writeEntry("SrcX",path->getSrcRoom()->getX()); 0213 pGroup.writeEntry("SrcY",path->getSrcRoom()->getY()); 0214 pGroup.writeEntry("DestX",path->getDestRoom()->getX()); 0215 pGroup.writeEntry("DestY",path->getDestRoom()->getY()); 0216 pGroup.writeEntry("SrcZone",path->getSrcRoom()->getZone()->getZoneID()); 0217 pGroup.writeEntry("DestZone",path->getDestRoom()->getZone()->getZoneID()); 0218 } 0219 0220 /** This method is called to copy the selected elements into the clipboard, then delete them */ 0221 void CMapClipboard::slotCut() 0222 { 0223 slotCopy(); 0224 slotDelete(); 0225 } 0226 0227 /** This method is called to paste the elements in the clipboard onto the current map */ 0228 void CMapClipboard::slotPaste() 0229 { 0230 m_mapManager->openCommandGroup("Paste"); 0231 0232 if (m_clipboard && m_mapManager->getActiveView()) 0233 { 0234 pasteElements(); 0235 pastePaths(); 0236 pasteLinks(); 0237 } 0238 0239 0240 m_mapManager->closeCommandGroup(); 0241 } 0242 0243 /** This method is used to paste elements that are not paths or linked text elements */ 0244 void CMapClipboard::pasteElements() 0245 { 0246 0247 // Paste the non path elements 0248 0249 // Get the number of elements in the clipboard 0250 KConfigGroup header = m_clipboard->group("Header"); 0251 int elements = header.readEntry("Elements",0); 0252 if (elements>0) 0253 { 0254 // Interate through each element in the clipboard 0255 for (int i=1;i<=elements; i++) 0256 { 0257 // Change to the group for the current element 0258 QString grp; 0259 grp.sprintf("%d",i); 0260 KConfigGroup group = m_clipboard->group(grp); 0261 0262 // Get the level number in the zone that the element is to be insterted into 0263 int levelNum = group.readEntry("LevelNum",-5); 0264 0265 // Get the zone that the element came from 0266 int orgZone = group.readEntry("Zone",-5); 0267 if (levelNum == -5 || orgZone == -5) 0268 { 0269 // The level num was not found so this is not a zone copy 0270 } 0271 else 0272 { 0273 CMapZone *zone = m_mapManager->getZone(); 0274 0275 // Check to see if the level exists and if not create it 0276 CMapLevel *level = nullptr; 0277 if (levelNum >= (int)zone->levelCount()) 0278 { 0279 level = m_mapManager->createLevel(UP); 0280 } 0281 else 0282 { 0283 level = zone->getLevel(levelNum); 0284 } 0285 0286 // Update the clipboard with the new level that the element is to be pasted into 0287 group.writeEntry("Level",level->getLevelID()); 0288 } 0289 0290 // Copy the properties to new properties the remove unwanted keys 0291 KMemConfig properties; 0292 KConfigGroup props = properties.group("Properties"); 0293 group.copyTo(&props); 0294 0295 int x = props.readEntry("X",-5); 0296 int y = props.readEntry("Y",-5); 0297 0298 props.writeEntry("X",x + m_mapManager->getMapData()->gridSize.width()); 0299 props.writeEntry("Y",y + m_mapManager->getMapData()->gridSize.height()); 0300 0301 // Create the command used to add a new element 0302 CMapCmdElementCreate *command = new CMapCmdElementCreate(m_mapManager,i18n("Paste Element")); 0303 0304 command->addElement(&properties,"Properties"); 0305 0306 // Execute the commmand 0307 m_mapManager->addCommand(command); 0308 0309 // Check the created elements to see if a zone was created 0310 QList<CMapElement *> *elements = command->getElements(); 0311 0312 foreach (CMapElement *el, *elements) 0313 { 0314 // Update the elements properties 0315 CMapCmdElementProperties *cmd = new CMapCmdElementProperties(m_mapManager,i18n("Update Properties"),el); 0316 cmd->setNewProperties(props); 0317 m_mapManager->addCommand(cmd); 0318 } 0319 } 0320 } 0321 } 0322 0323 /** This method is used to paste path elements */ 0324 void CMapClipboard::pastePaths() 0325 { 0326 // Paste the path elements 0327 // Get the number of elements in the clipboard 0328 KConfigGroup header = m_clipboard->group("Header"); 0329 int paths = header.readEntry("Paths",0); 0330 0331 if (paths>0) 0332 { 0333 // Interate through each element in the clipboard 0334 for (int i=1;i<=paths; i++) 0335 { 0336 // Change to the group for the current element 0337 QString grp; 0338 grp.sprintf("PATH%d",i); 0339 KConfigGroup group = m_clipboard->group(grp); 0340 0341 int srcLevelNum = group.readEntry("SrcLevelNum",-5); 0342 int destLevelNum = group.readEntry("DestLevelNum",-5); 0343 0344 if (srcLevelNum==-5 || destLevelNum ==-5) 0345 { 0346 // Should never get here 0347 } 0348 else 0349 { 0350 // Lookup witch zone the element is to be pasted into 0351 CMapZone *zone = m_mapManager->getZone(); 0352 0353 // Check to see if the level exists and if not create it 0354 CMapLevel *srcLevel = zone->getLevel(srcLevelNum); 0355 CMapLevel *destLevel = zone->getLevel(destLevelNum); 0356 0357 KMemConfig properties; 0358 KConfigGroup props = properties.group("Properties"); 0359 group.copyTo(&props); 0360 0361 int srcX = props.readEntry("SrcX",-5); 0362 int srcY = props.readEntry("SrcY",-5); 0363 0364 srcX+=m_mapManager->getMapData()->gridSize.width(); 0365 srcY+=m_mapManager->getMapData()->gridSize.height(); 0366 0367 int destX = props.readEntry("DestX",-5); 0368 int destY = props.readEntry("DestY",-5); 0369 0370 destX+=m_mapManager->getMapData()->gridSize.width(); 0371 destY+=m_mapManager->getMapData()->gridSize.height(); 0372 0373 // Update the clipboard with the new level that the element is to be pasted into 0374 props.writeEntry("SrcRoom", srcLevel->findRoomAt(QPoint(srcX,srcY))->getRoomID()); 0375 props.writeEntry("DestRoom", destLevel->findRoomAt(QPoint(destX,destY))->getRoomID()); 0376 props.writeEntry("SrcLevel",srcLevel->getLevelID()); 0377 props.writeEntry("DestLevel",destLevel->getLevelID()); 0378 0379 // Create the command used to add a new element and the execute it 0380 CMapCmdElementCreate *command = new CMapCmdElementCreate(m_mapManager,i18n("Paste Path")); 0381 command->addElement(&properties); 0382 m_mapManager->addCommand(command); 0383 } 0384 } 0385 } 0386 } 0387 0388 /** This method is used to update linked text elements with the correct properties from the clibboard */ 0389 void CMapClipboard::pasteLinks() 0390 { 0391 // Update link elements with the correct properties 0392 KConfigGroup header = m_clipboard->group("Header"); 0393 int links = header.readEntry("Links",0); 0394 0395 if (links>0) 0396 { 0397 // Interate through each element in the clipboard 0398 for (int i=1;i<=links; i++) 0399 { 0400 // Change to the group for the current element 0401 QString grp; 0402 grp.sprintf("LINK%d",i); 0403 KConfigGroup group = m_clipboard->group(grp); 0404 0405 int linkLevelNum = group.readEntry("LinkLevelNum",-5); 0406 0407 if (linkLevelNum==-5) 0408 { 0409 // Should never get here 0410 } 0411 else 0412 { 0413 // Get the zone that the element came from 0414 CMapZone *zone = m_mapManager->getZone(); 0415 0416 // Check to see if the level exists and if not create it 0417 CMapLevel *linkLevel = zone->getLevel(linkLevelNum); 0418 0419 // Copy link text element properties to new properties 0420 KMemConfig properties; 0421 KConfigGroup props = properties.group("Properties"); 0422 group.copyTo(&props); 0423 0424 // Get cordianets of text element and linked element, and adjust them for any offsets 0425 int x = props.readEntry("LinkX",-5); 0426 int y = props.readEntry("LinkY",-5); 0427 0428 x+=m_mapManager->getMapData()->gridSize.width(); 0429 y+=m_mapManager->getMapData()->gridSize.height(); 0430 0431 int textX = props.readEntry("X",-5); 0432 int textY = props.readEntry("Y",-5); 0433 props.writeEntry("X",textX + m_mapManager->getMapData()->gridSize.width()); 0434 props.writeEntry("Y",textY + m_mapManager->getMapData()->gridSize.height()); 0435 0436 // Setup the properties so that the text element will be linked to the new element 0437 CMapElement *link = linkLevel->findElementAt(QPoint(x,y)); 0438 if (link->getElementType()==ZONE) 0439 { 0440 props.writeEntry("LinkedID",((CMapZone *)link)->getZoneID()); 0441 } 0442 else 0443 { 0444 props.writeEntry("LinkedID",((CMapRoom *)link)->getRoomID()); 0445 } 0446 props.writeEntry("LinkedLevel",link->getLevel()->getLevelID()); 0447 0448 // Create the command used to add a new element 0449 CMapCmdElementCreate *command = new CMapCmdElementCreate(m_mapManager,i18n("Paste Element")); 0450 command->addElement(&properties,"Properties"); 0451 m_mapManager->addCommand(command); 0452 0453 // Check the created elements to see if a zone was created 0454 QList<CMapElement *> *elements=command->getElements(); 0455 0456 foreach (CMapElement *el, *elements) 0457 { 0458 // Update the elements properties 0459 CMapCmdElementProperties *cmd = new CMapCmdElementProperties(m_mapManager,i18n("Update Properties"),el); 0460 cmd->setNewProperties(props); 0461 m_mapManager->addCommand(cmd); 0462 } 0463 } 0464 } 0465 } 0466 } 0467 0468 0469 /** This slot is called to delete all the selected objects in the current view */ 0470 void CMapClipboard::slotDelete(void) 0471 { 0472 m_mapManager->openCommandGroup(i18n("Delete Elements")); 0473 CMapView *currentView = m_mapManager->getActiveView(); 0474 if (currentView) 0475 { 0476 CMapLevel *level = currentView->getCurrentlyViewedLevel(); 0477 0478 if (level) 0479 { 0480 QList<CMapElement *> lst = level->getAllElements(); 0481 foreach (CMapElement *el, lst) 0482 if (el->getSelected()) 0483 m_mapManager->deleteElement(el); 0484 } 0485 } 0486 0487 m_mapManager->closeCommandGroup(); 0488 } 0489 0490 /** This slot is called when the select all menu option is selected */ 0491 void CMapClipboard::slotSelectAll(void) 0492 { 0493 if (m_mapManager->getActiveView()) 0494 { 0495 CMapLevel *level = m_mapManager->getActiveView()->getCurrentlyViewedLevel(); 0496 QList<CMapElement *> lst = level->getAllElements(); 0497 foreach (CMapElement *element, lst) 0498 element->setSelected(true); 0499 0500 m_mapManager->levelChanged(level); 0501 } 0502 } 0503 0504 /** This slot is called when the unselect all menu option is selected */ 0505 void CMapClipboard::slotUnselectAll(void) 0506 { 0507 if (m_mapManager->getActiveView()) 0508 { 0509 m_mapManager->unselectElements(m_mapManager->getActiveView()->getCurrentlyViewedLevel()); 0510 0511 m_mapManager->levelChanged(m_mapManager->getActiveView()->getCurrentlyViewedLevel()); 0512 } 0513 } 0514 0515 /** This slot is called when the invert selection menu option is called */ 0516 void CMapClipboard::slotInvertSelection(void) 0517 { 0518 if (!m_mapManager->getActiveView()) return; 0519 CMapLevel *level = m_mapManager->getActiveView()->getCurrentlyViewedLevel(); 0520 0521 QList<CMapElement *> lst = level->getAllElements(); 0522 foreach (CMapElement *element, lst) 0523 element->setSelected(!element->getSelected()); 0524 0525 m_mapManager->levelChanged(m_mapManager->getActiveView()->getCurrentlyViewedLevel()); 0526 } 0527 0528 #include "moc_cmapclipboard.cpp"