File indexing completed on 2024-12-01 06:51:42
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 <KLocalizedString> 0022 0023 #include <QAction> 0024 #include <QDebug> 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 qDebug() << "CMapClipboard::CMapClipboard constructor begins"; 0045 0046 m_clipboard = nullptr; 0047 initActions(); 0048 qDebug() << "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 = QString::number(group); 0124 KConfigGroup clipGroup = m_clipboard->group(grp); 0125 0126 switch (element->getElementType()) 0127 { 0128 case ROOM : { 0129 CMapRoom *room = (CMapRoom *)element; 0130 room->saveProperties(clipGroup); 0131 clipGroup.deleteEntry("RoomID"); 0132 clipGroup.writeEntry("LabelPos",(int)CMapRoom::HIDE); 0133 } 0134 break; 0135 case TEXT : if (!((CMapText *)element)->getLinkElement()) 0136 { 0137 element->saveProperties(clipGroup); 0138 clipGroup.deleteEntry("TextID"); 0139 } 0140 break; 0141 default : break; 0142 } 0143 } 0144 0145 // Copy all the path elements into the clipboard 0146 int pathGroup = 0; 0147 0148 for (unsigned int idx = 0; idx < m_mapManager->getZone()->levelCount(); ++idx) 0149 { 0150 CMapLevel *level = m_mapManager->getZone()->getLevel(idx); 0151 0152 foreach (CMapRoom *room, *level->getRoomList()) 0153 { 0154 foreach (CMapPath *path, *room->getPathList()) 0155 { 0156 if ((path->getSrcRoom()->getSelected() || path->getSrcRoom()->getZone()->getSelected()) && 0157 (path->getDestRoom()->getSelected() || path->getDestRoom()->getZone()->getSelected())) 0158 { 0159 copyPath (&pathGroup,path); 0160 } 0161 } 0162 } 0163 } 0164 0165 // Copy all the linked text elements 0166 int linkGroup =0; 0167 0168 foreach (CMapElement *element, lst) 0169 { 0170 if (element->getSelected() && element->getElementType()==TEXT) 0171 { 0172 CMapText *text = (CMapText *)element; 0173 CMapElement *link = text->getLinkElement(); 0174 if (link) 0175 { 0176 linkGroup++; 0177 QString grp = "LINK" + QString::number(linkGroup); 0178 KConfigGroup clipGroup = m_clipboard->group(grp); 0179 0180 text->saveProperties(clipGroup); 0181 0182 clipGroup.writeEntry("LinkLevelNum",link->getLevel()->getNumber()); 0183 0184 clipGroup.writeEntry("LinkX",link->getX()); 0185 clipGroup.writeEntry("LinkY",link->getY()); 0186 clipGroup.writeEntry("LinkZone",link->getZone()->getZoneID()); 0187 } 0188 } 0189 } 0190 0191 // Copy the selected paths 0192 KConfigGroup header = m_clipboard->group("Header"); 0193 header.writeEntry("Elements",group); 0194 header.writeEntry("Paths",pathGroup); 0195 header.writeEntry("Links",linkGroup); 0196 } 0197 } 0198 0199 /** This method is used to copy a path into the clipboard */ 0200 void CMapClipboard::copyPath(int *pathGroup,CMapPath *path) 0201 { 0202 (*pathGroup)++; 0203 QString grp = "PATH" + QString::number(*pathGroup); 0204 KConfigGroup pGroup = m_clipboard->group(grp); 0205 0206 path->saveProperties(pGroup); 0207 pGroup.writeEntry("SrcLevelNum",path->getSrcRoom()->getLevel()->getNumber()); 0208 pGroup.writeEntry("DestLevelNum",path->getDestRoom()->getLevel()->getNumber()); 0209 pGroup.writeEntry("SrcX",path->getSrcRoom()->getX()); 0210 pGroup.writeEntry("SrcY",path->getSrcRoom()->getY()); 0211 pGroup.writeEntry("DestX",path->getDestRoom()->getX()); 0212 pGroup.writeEntry("DestY",path->getDestRoom()->getY()); 0213 pGroup.writeEntry("SrcZone",path->getSrcRoom()->getZone()->getZoneID()); 0214 pGroup.writeEntry("DestZone",path->getDestRoom()->getZone()->getZoneID()); 0215 } 0216 0217 /** This method is called to copy the selected elements into the clipboard, then delete them */ 0218 void CMapClipboard::slotCut() 0219 { 0220 slotCopy(); 0221 slotDelete(); 0222 } 0223 0224 /** This method is called to paste the elements in the clipboard onto the current map */ 0225 void CMapClipboard::slotPaste() 0226 { 0227 m_mapManager->openCommandGroup("Paste"); 0228 0229 if (m_clipboard && m_mapManager->getActiveView()) 0230 { 0231 pasteElements(); 0232 pastePaths(); 0233 pasteLinks(); 0234 } 0235 0236 0237 m_mapManager->closeCommandGroup(); 0238 } 0239 0240 /** This method is used to paste elements that are not paths or linked text elements */ 0241 void CMapClipboard::pasteElements() 0242 { 0243 0244 // Paste the non path elements 0245 0246 // Get the number of elements in the clipboard 0247 KConfigGroup header = m_clipboard->group("Header"); 0248 int elements = header.readEntry("Elements",0); 0249 if (elements>0) 0250 { 0251 // Interate through each element in the clipboard 0252 for (int i=1;i<=elements; i++) 0253 { 0254 // Change to the group for the current element 0255 QString grp = QString::number(i); 0256 KConfigGroup group = m_clipboard->group(grp); 0257 0258 // Get the level number in the zone that the element is to be insterted into 0259 int levelNum = group.readEntry("LevelNum",-5); 0260 0261 // Get the zone that the element came from 0262 int orgZone = group.readEntry("Zone",-5); 0263 if (levelNum == -5 || orgZone == -5) 0264 { 0265 // The level num was not found so this is not a zone copy 0266 } 0267 else 0268 { 0269 CMapZone *zone = m_mapManager->getZone(); 0270 0271 // Check to see if the level exists and if not create it 0272 CMapLevel *level = nullptr; 0273 if (levelNum >= (int)zone->levelCount()) 0274 { 0275 level = m_mapManager->createLevel(UP); 0276 } 0277 else 0278 { 0279 level = zone->getLevel(levelNum); 0280 } 0281 0282 // Update the clipboard with the new level that the element is to be pasted into 0283 group.writeEntry("Level",level->getLevelID()); 0284 } 0285 0286 // Copy the properties to new properties the remove unwanted keys 0287 KMemConfig properties; 0288 KConfigGroup props = properties.group("Properties"); 0289 group.copyTo(&props); 0290 0291 int x = props.readEntry("X",-5); 0292 int y = props.readEntry("Y",-5); 0293 0294 props.writeEntry("X",x + m_mapManager->getMapData()->gridSize.width()); 0295 props.writeEntry("Y",y + m_mapManager->getMapData()->gridSize.height()); 0296 0297 // Create the command used to add a new element 0298 CMapCmdElementCreate *command = new CMapCmdElementCreate(m_mapManager,i18n("Paste Element")); 0299 0300 command->addElement(&properties,"Properties"); 0301 0302 // Execute the commmand 0303 m_mapManager->addCommand(command); 0304 0305 // Check the created elements to see if a zone was created 0306 QList<CMapElement *> *elements = command->getElements(); 0307 0308 foreach (CMapElement *el, *elements) 0309 { 0310 // Update the elements properties 0311 CMapCmdElementProperties *cmd = new CMapCmdElementProperties(m_mapManager,i18n("Update Properties"),el); 0312 cmd->setNewProperties(props); 0313 m_mapManager->addCommand(cmd); 0314 } 0315 } 0316 } 0317 } 0318 0319 /** This method is used to paste path elements */ 0320 void CMapClipboard::pastePaths() 0321 { 0322 // Paste the path elements 0323 // Get the number of elements in the clipboard 0324 KConfigGroup header = m_clipboard->group("Header"); 0325 int paths = header.readEntry("Paths",0); 0326 0327 if (paths>0) 0328 { 0329 // Interate through each element in the clipboard 0330 for (int i=1;i<=paths; i++) 0331 { 0332 // Change to the group for the current element 0333 QString grp = "PATH" + QString::number(i); 0334 KConfigGroup group = m_clipboard->group(grp); 0335 0336 int srcLevelNum = group.readEntry("SrcLevelNum",-5); 0337 int destLevelNum = group.readEntry("DestLevelNum",-5); 0338 0339 if (srcLevelNum==-5 || destLevelNum ==-5) 0340 { 0341 // Should never get here 0342 } 0343 else 0344 { 0345 // Lookup witch zone the element is to be pasted into 0346 CMapZone *zone = m_mapManager->getZone(); 0347 0348 // Check to see if the level exists and if not create it 0349 CMapLevel *srcLevel = zone->getLevel(srcLevelNum); 0350 CMapLevel *destLevel = zone->getLevel(destLevelNum); 0351 0352 KMemConfig properties; 0353 KConfigGroup props = properties.group("Properties"); 0354 group.copyTo(&props); 0355 0356 int srcX = props.readEntry("SrcX",-5); 0357 int srcY = props.readEntry("SrcY",-5); 0358 0359 srcX+=m_mapManager->getMapData()->gridSize.width(); 0360 srcY+=m_mapManager->getMapData()->gridSize.height(); 0361 0362 int destX = props.readEntry("DestX",-5); 0363 int destY = props.readEntry("DestY",-5); 0364 0365 destX+=m_mapManager->getMapData()->gridSize.width(); 0366 destY+=m_mapManager->getMapData()->gridSize.height(); 0367 0368 // Update the clipboard with the new level that the element is to be pasted into 0369 props.writeEntry("SrcRoom", srcLevel->findRoomAt(QPoint(srcX,srcY))->getRoomID()); 0370 props.writeEntry("DestRoom", destLevel->findRoomAt(QPoint(destX,destY))->getRoomID()); 0371 props.writeEntry("SrcLevel",srcLevel->getLevelID()); 0372 props.writeEntry("DestLevel",destLevel->getLevelID()); 0373 0374 // Create the command used to add a new element and the execute it 0375 CMapCmdElementCreate *command = new CMapCmdElementCreate(m_mapManager,i18n("Paste Path")); 0376 command->addElement(&properties); 0377 m_mapManager->addCommand(command); 0378 } 0379 } 0380 } 0381 } 0382 0383 /** This method is used to update linked text elements with the correct properties from the clibboard */ 0384 void CMapClipboard::pasteLinks() 0385 { 0386 // Update link elements with the correct properties 0387 KConfigGroup header = m_clipboard->group("Header"); 0388 int links = header.readEntry("Links",0); 0389 0390 if (links>0) 0391 { 0392 // Interate through each element in the clipboard 0393 for (int i=1;i<=links; i++) 0394 { 0395 // Change to the group for the current element 0396 QString grp = "LINK" + QString::number(i); 0397 KConfigGroup group = m_clipboard->group(grp); 0398 0399 int linkLevelNum = group.readEntry("LinkLevelNum",-5); 0400 0401 if (linkLevelNum==-5) 0402 { 0403 // Should never get here 0404 } 0405 else 0406 { 0407 // Get the zone that the element came from 0408 CMapZone *zone = m_mapManager->getZone(); 0409 0410 // Check to see if the level exists and if not create it 0411 CMapLevel *linkLevel = zone->getLevel(linkLevelNum); 0412 0413 // Copy link text element properties to new properties 0414 KMemConfig properties; 0415 KConfigGroup props = properties.group("Properties"); 0416 group.copyTo(&props); 0417 0418 // Get cordianets of text element and linked element, and adjust them for any offsets 0419 int x = props.readEntry("LinkX",-5); 0420 int y = props.readEntry("LinkY",-5); 0421 0422 x+=m_mapManager->getMapData()->gridSize.width(); 0423 y+=m_mapManager->getMapData()->gridSize.height(); 0424 0425 int textX = props.readEntry("X",-5); 0426 int textY = props.readEntry("Y",-5); 0427 props.writeEntry("X",textX + m_mapManager->getMapData()->gridSize.width()); 0428 props.writeEntry("Y",textY + m_mapManager->getMapData()->gridSize.height()); 0429 0430 // Setup the properties so that the text element will be linked to the new element 0431 CMapElement *link = linkLevel->findElementAt(QPoint(x,y)); 0432 if (link->getElementType()==ZONE) 0433 { 0434 props.writeEntry("LinkedID",((CMapZone *)link)->getZoneID()); 0435 } 0436 else 0437 { 0438 props.writeEntry("LinkedID",((CMapRoom *)link)->getRoomID()); 0439 } 0440 props.writeEntry("LinkedLevel",link->getLevel()->getLevelID()); 0441 0442 // Create the command used to add a new element 0443 CMapCmdElementCreate *command = new CMapCmdElementCreate(m_mapManager,i18n("Paste Element")); 0444 command->addElement(&properties,"Properties"); 0445 m_mapManager->addCommand(command); 0446 0447 // Check the created elements to see if a zone was created 0448 QList<CMapElement *> *elements=command->getElements(); 0449 0450 foreach (CMapElement *el, *elements) 0451 { 0452 // Update the elements properties 0453 CMapCmdElementProperties *cmd = new CMapCmdElementProperties(m_mapManager,i18n("Update Properties"),el); 0454 cmd->setNewProperties(props); 0455 m_mapManager->addCommand(cmd); 0456 } 0457 } 0458 } 0459 } 0460 } 0461 0462 0463 /** This slot is called to delete all the selected objects in the current view */ 0464 void CMapClipboard::slotDelete(void) 0465 { 0466 m_mapManager->openCommandGroup(i18n("Delete Elements")); 0467 CMapView *currentView = m_mapManager->getActiveView(); 0468 if (currentView) 0469 { 0470 CMapLevel *level = currentView->getCurrentlyViewedLevel(); 0471 0472 if (level) 0473 { 0474 QList<CMapElement *> lst = level->getAllElements(); 0475 foreach (CMapElement *el, lst) 0476 if (el->getSelected()) 0477 m_mapManager->deleteElement(el); 0478 } 0479 } 0480 0481 m_mapManager->closeCommandGroup(); 0482 } 0483 0484 /** This slot is called when the select all menu option is selected */ 0485 void CMapClipboard::slotSelectAll(void) 0486 { 0487 if (m_mapManager->getActiveView()) 0488 { 0489 CMapLevel *level = m_mapManager->getActiveView()->getCurrentlyViewedLevel(); 0490 QList<CMapElement *> lst = level->getAllElements(); 0491 foreach (CMapElement *element, lst) 0492 element->setSelected(true); 0493 0494 m_mapManager->levelChanged(level); 0495 } 0496 } 0497 0498 /** This slot is called when the unselect all menu option is selected */ 0499 void CMapClipboard::slotUnselectAll(void) 0500 { 0501 if (m_mapManager->getActiveView()) 0502 { 0503 m_mapManager->unselectElements(m_mapManager->getActiveView()->getCurrentlyViewedLevel()); 0504 0505 m_mapManager->levelChanged(m_mapManager->getActiveView()->getCurrentlyViewedLevel()); 0506 } 0507 } 0508 0509 /** This slot is called when the invert selection menu option is called */ 0510 void CMapClipboard::slotInvertSelection(void) 0511 { 0512 if (!m_mapManager->getActiveView()) return; 0513 CMapLevel *level = m_mapManager->getActiveView()->getCurrentlyViewedLevel(); 0514 0515 QList<CMapElement *> lst = level->getAllElements(); 0516 foreach (CMapElement *element, lst) 0517 element->setSelected(!element->getSelected()); 0518 0519 m_mapManager->levelChanged(m_mapManager->getActiveView()->getCurrentlyViewedLevel()); 0520 } 0521 0522 #include "moc_cmapclipboard.cpp"