File indexing completed on 2024-04-28 04:31:55
0001 /* 0002 * Copyright (C) 2010-2015 by Stephen Allewell 0003 * steve.allewell@gmail.com 0004 * 0005 * This program is free software; you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation; either version 2 of the License, or 0008 * (at your option) any later version. 0009 */ 0010 0011 #include "Commands.h" 0012 0013 #include <QApplication> 0014 #include <QClipboard> 0015 #include <QMimeData> 0016 0017 #include <KLocalizedString> 0018 0019 #include "BackgroundImage.h" 0020 #include "Document.h" 0021 #include "Editor.h" 0022 #include "Floss.h" 0023 #include "FlossScheme.h" 0024 #include "MainWindow.h" 0025 #include "Palette.h" 0026 #include "Preview.h" 0027 #include "SchemeManager.h" 0028 #include "StitchData.h" 0029 0030 FilePropertiesCommand::FilePropertiesCommand(Document *document) 0031 : QUndoCommand(i18n("File Properties")) 0032 , m_document(document) 0033 { 0034 } 0035 0036 void FilePropertiesCommand::redo() 0037 { 0038 QUndoCommand::redo(); 0039 m_document->editor()->readDocumentSettings(); 0040 m_document->preview()->readDocumentSettings(); 0041 m_document->palette()->update(); 0042 } 0043 0044 void FilePropertiesCommand::undo() 0045 { 0046 QUndoCommand::undo(); 0047 m_document->editor()->readDocumentSettings(); 0048 m_document->preview()->readDocumentSettings(); 0049 m_document->palette()->update(); 0050 } 0051 0052 ImportImageCommand::ImportImageCommand(Document *document) 0053 : QUndoCommand(i18n("Import Image")) 0054 , m_document(document) 0055 { 0056 } 0057 0058 void ImportImageCommand::redo() 0059 { 0060 QUndoCommand::redo(); 0061 m_document->editor()->readDocumentSettings(); 0062 m_document->preview()->readDocumentSettings(); 0063 m_document->palette()->update(); 0064 } 0065 0066 void ImportImageCommand::undo() 0067 { 0068 QUndoCommand::undo(); 0069 m_document->editor()->readDocumentSettings(); 0070 m_document->preview()->readDocumentSettings(); 0071 m_document->palette()->update(); 0072 } 0073 0074 PaintStitchesCommand::PaintStitchesCommand(Document *document) 0075 : QUndoCommand(i18n("Paint Stitches")) 0076 , m_document(document) 0077 { 0078 } 0079 0080 void PaintStitchesCommand::redo() 0081 { 0082 QUndoCommand::redo(); 0083 m_document->editor()->drawContents(); 0084 m_document->preview()->drawContents(); 0085 } 0086 0087 void PaintStitchesCommand::undo() 0088 { 0089 QUndoCommand::undo(); 0090 m_document->editor()->drawContents(); 0091 m_document->preview()->drawContents(); 0092 } 0093 0094 PaintKnotsCommand::PaintKnotsCommand(Document *document) 0095 : QUndoCommand(i18n("Paint Knots")) 0096 , m_document(document) 0097 { 0098 } 0099 0100 void PaintKnotsCommand::redo() 0101 { 0102 QUndoCommand::redo(); 0103 m_document->editor()->drawContents(); 0104 m_document->preview()->drawContents(); 0105 } 0106 0107 void PaintKnotsCommand::undo() 0108 { 0109 QUndoCommand::undo(); 0110 m_document->editor()->drawContents(); 0111 m_document->preview()->drawContents(); 0112 } 0113 0114 DrawLineCommand::DrawLineCommand(Document *document) 0115 : QUndoCommand(i18n("Draw Line")) 0116 , m_document(document) 0117 { 0118 } 0119 0120 void DrawLineCommand::redo() 0121 { 0122 QUndoCommand::redo(); 0123 m_document->editor()->drawContents(); 0124 m_document->preview()->drawContents(); 0125 } 0126 0127 void DrawLineCommand::undo() 0128 { 0129 QUndoCommand::undo(); 0130 m_document->editor()->drawContents(); 0131 m_document->preview()->drawContents(); 0132 } 0133 0134 EraseStitchesCommand::EraseStitchesCommand(Document *document) 0135 : QUndoCommand(i18n("Erase Stitches")) 0136 , m_document(document) 0137 { 0138 } 0139 0140 void EraseStitchesCommand::redo() 0141 { 0142 QUndoCommand::redo(); 0143 m_document->editor()->drawContents(); 0144 m_document->preview()->drawContents(); 0145 } 0146 0147 void EraseStitchesCommand::undo() 0148 { 0149 QUndoCommand::undo(); 0150 m_document->editor()->drawContents(); 0151 m_document->preview()->drawContents(); 0152 } 0153 0154 DrawRectangleCommand::DrawRectangleCommand(Document *document) 0155 : QUndoCommand(i18n("Draw Rectangle")) 0156 , m_document(document) 0157 { 0158 } 0159 0160 void DrawRectangleCommand::redo() 0161 { 0162 QUndoCommand::redo(); 0163 m_document->editor()->drawContents(); 0164 m_document->preview()->drawContents(); 0165 } 0166 0167 void DrawRectangleCommand::undo() 0168 { 0169 QUndoCommand::undo(); 0170 m_document->editor()->drawContents(); 0171 m_document->preview()->drawContents(); 0172 } 0173 0174 FillRectangleCommand::FillRectangleCommand(Document *document) 0175 : QUndoCommand(i18n("Fill Rectangle")) 0176 , m_document(document) 0177 { 0178 } 0179 0180 void FillRectangleCommand::redo() 0181 { 0182 QUndoCommand::redo(); 0183 m_document->editor()->drawContents(); 0184 m_document->preview()->drawContents(); 0185 } 0186 0187 void FillRectangleCommand::undo() 0188 { 0189 QUndoCommand::undo(); 0190 m_document->editor()->drawContents(); 0191 m_document->preview()->drawContents(); 0192 } 0193 0194 DrawEllipseCommand::DrawEllipseCommand(Document *document) 0195 : QUndoCommand(i18n("Draw Ellipse")) 0196 , m_document(document) 0197 { 0198 } 0199 0200 void DrawEllipseCommand::redo() 0201 { 0202 QUndoCommand::redo(); 0203 m_document->editor()->drawContents(); 0204 m_document->preview()->drawContents(); 0205 } 0206 0207 void DrawEllipseCommand::undo() 0208 { 0209 QUndoCommand::undo(); 0210 m_document->editor()->drawContents(); 0211 m_document->preview()->drawContents(); 0212 } 0213 0214 FillEllipseCommand::FillEllipseCommand(Document *document) 0215 : QUndoCommand(i18n("Fill Ellipse")) 0216 , m_document(document) 0217 { 0218 } 0219 0220 void FillEllipseCommand::redo() 0221 { 0222 QUndoCommand::redo(); 0223 m_document->editor()->drawContents(); 0224 m_document->preview()->drawContents(); 0225 } 0226 0227 void FillEllipseCommand::undo() 0228 { 0229 QUndoCommand::undo(); 0230 m_document->editor()->drawContents(); 0231 m_document->preview()->drawContents(); 0232 } 0233 0234 FillPolygonCommand::FillPolygonCommand(Document *document) 0235 : QUndoCommand(i18n("Fill Polygon")) 0236 , m_document(document) 0237 { 0238 } 0239 0240 void FillPolygonCommand::redo() 0241 { 0242 QUndoCommand::redo(); 0243 m_document->editor()->drawContents(); 0244 m_document->preview()->drawContents(); 0245 } 0246 0247 void FillPolygonCommand::undo() 0248 { 0249 QUndoCommand::undo(); 0250 m_document->editor()->drawContents(); 0251 m_document->preview()->drawContents(); 0252 } 0253 0254 AddStitchCommand::AddStitchCommand(Document *document, const QPoint &location, Stitch::Type type, int colorIndex, QUndoCommand *parent) 0255 : QUndoCommand(i18n("Add Stitch"), parent) 0256 , m_document(document) 0257 , m_cell(location) 0258 , m_type(type) 0259 , m_colorIndex(colorIndex) 0260 , m_original(nullptr) 0261 { 0262 } 0263 0264 AddStitchCommand::~AddStitchCommand() 0265 { 0266 delete m_original; 0267 } 0268 0269 void AddStitchCommand::redo() 0270 { 0271 m_original = m_document->pattern()->stitches().stitchQueueAt(m_cell); 0272 0273 if (m_original) { 0274 m_document->pattern()->stitches().replaceStitchQueueAt(m_cell, new StitchQueue(m_original)); 0275 } 0276 0277 m_document->pattern()->stitches().addStitch(m_cell, m_type, m_colorIndex); 0278 } 0279 0280 void AddStitchCommand::undo() 0281 { 0282 delete m_document->pattern()->stitches().takeStitchQueueAt(m_cell); 0283 0284 if (m_original) { 0285 m_document->pattern()->stitches().replaceStitchQueueAt(m_cell, m_original); 0286 m_original = nullptr; 0287 } 0288 } 0289 0290 DeleteStitchCommand::DeleteStitchCommand(Document *document, const QPoint &cell, Stitch::Type type, int colorIndex, QUndoCommand *parent) 0291 : QUndoCommand(i18n("Delete Stitches"), parent) 0292 , m_document(document) 0293 , m_cell(cell) 0294 , m_type(type) 0295 , m_colorIndex(colorIndex) 0296 , m_original(nullptr) 0297 { 0298 } 0299 0300 DeleteStitchCommand::~DeleteStitchCommand() 0301 { 0302 delete m_original; 0303 } 0304 0305 void DeleteStitchCommand::redo() 0306 { 0307 m_original = m_document->pattern()->stitches().stitchQueueAt(m_cell); 0308 0309 if (m_original) { 0310 m_original = m_document->pattern()->stitches().replaceStitchQueueAt(m_cell, new StitchQueue(m_original)); 0311 m_document->pattern()->stitches().deleteStitch(m_cell, m_type, m_colorIndex); 0312 } 0313 } 0314 0315 void DeleteStitchCommand::undo() 0316 { 0317 if (m_original) { 0318 delete m_document->pattern()->stitches().replaceStitchQueueAt(m_cell, m_original); 0319 m_original = nullptr; 0320 } 0321 } 0322 0323 AddBackstitchCommand::AddBackstitchCommand(Document *document, const QPoint &start, const QPoint &end, int colorIndex) 0324 : QUndoCommand(i18n("Add Backstitch")) 0325 , m_document(document) 0326 , m_start(start) 0327 , m_end(end) 0328 , m_colorIndex(colorIndex) 0329 { 0330 } 0331 0332 void AddBackstitchCommand::redo() 0333 { 0334 m_document->pattern()->stitches().addBackstitch(m_start, m_end, m_colorIndex); 0335 m_document->editor()->drawContents(); 0336 m_document->preview()->drawContents(); 0337 } 0338 0339 void AddBackstitchCommand::undo() 0340 { 0341 delete m_document->pattern()->stitches().takeBackstitch(m_start, m_end, m_colorIndex); 0342 m_document->editor()->drawContents(); 0343 m_document->preview()->drawContents(); 0344 } 0345 0346 DeleteBackstitchCommand::DeleteBackstitchCommand(Document *document, const QPoint &start, const QPoint &end, int colorIndex) 0347 : QUndoCommand(i18n("Delete Backstitch")) 0348 , m_document(document) 0349 , m_start(start) 0350 , m_end(end) 0351 , m_colorIndex(colorIndex) 0352 , m_backstitch(nullptr) 0353 { 0354 } 0355 0356 DeleteBackstitchCommand::~DeleteBackstitchCommand() 0357 { 0358 delete m_backstitch; 0359 } 0360 0361 void DeleteBackstitchCommand::redo() 0362 { 0363 m_backstitch = m_document->pattern()->stitches().takeBackstitch(m_start, m_end, m_colorIndex); 0364 m_document->editor()->drawContents(); 0365 m_document->preview()->drawContents(); 0366 } 0367 0368 void DeleteBackstitchCommand::undo() 0369 { 0370 m_document->pattern()->stitches().addBackstitch(m_backstitch); 0371 m_backstitch = nullptr; 0372 m_document->editor()->drawContents(); 0373 m_document->preview()->drawContents(); 0374 } 0375 0376 AddKnotCommand::AddKnotCommand(Document *document, const QPoint &snap, int colorIndex, QUndoCommand *parent) 0377 : QUndoCommand(i18n("Add Knot"), parent) 0378 , m_document(document) 0379 , m_snap(snap) 0380 , m_colorIndex(colorIndex) 0381 { 0382 } 0383 0384 void AddKnotCommand::redo() 0385 { 0386 m_document->pattern()->stitches().addFrenchKnot(m_snap, m_colorIndex); 0387 } 0388 0389 void AddKnotCommand::undo() 0390 { 0391 delete m_document->pattern()->stitches().takeFrenchKnot(m_snap, m_colorIndex); 0392 } 0393 0394 DeleteKnotCommand::DeleteKnotCommand(Document *document, const QPoint &snap, int colorIndex, QUndoCommand *parent) 0395 : QUndoCommand(i18n("Delete Knots"), parent) 0396 , m_document(document) 0397 , m_snap(snap) 0398 , m_colorIndex(colorIndex) 0399 , m_knot(nullptr) 0400 { 0401 } 0402 0403 DeleteKnotCommand::~DeleteKnotCommand() 0404 { 0405 delete m_knot; 0406 } 0407 0408 void DeleteKnotCommand::redo() 0409 { 0410 m_knot = m_document->pattern()->stitches().takeFrenchKnot(m_snap, m_colorIndex); 0411 } 0412 0413 void DeleteKnotCommand::undo() 0414 { 0415 m_document->pattern()->stitches().addFrenchKnot(m_knot); 0416 m_knot = nullptr; 0417 } 0418 0419 SetPropertyCommand::SetPropertyCommand(Document *document, const QString &name, const QVariant &value, QUndoCommand *parent) 0420 : QUndoCommand(i18n("Set Property"), parent) 0421 , m_document(document) 0422 , m_name(name) 0423 , m_value(value) 0424 { 0425 } 0426 0427 void SetPropertyCommand::redo() 0428 { 0429 m_oldValue = m_document->property(m_name); 0430 m_document->setProperty(m_name, m_value); 0431 } 0432 0433 void SetPropertyCommand::undo() 0434 { 0435 m_document->setProperty(m_name, m_oldValue); 0436 } 0437 0438 AddBackgroundImageCommand::AddBackgroundImageCommand(Document *document, QSharedPointer<BackgroundImage> backgroundImage, MainWindow *mainWindow) 0439 : QUndoCommand(i18n("Add Background Image")) 0440 , m_document(document) 0441 , m_backgroundImage(backgroundImage) 0442 , m_mainWindow(mainWindow) 0443 { 0444 } 0445 0446 void AddBackgroundImageCommand::redo() 0447 { 0448 m_document->backgroundImages().addBackgroundImage(m_backgroundImage); 0449 m_mainWindow->updateBackgroundImageActionLists(); 0450 m_document->editor()->drawContents(); 0451 } 0452 0453 void AddBackgroundImageCommand::undo() 0454 { 0455 m_document->backgroundImages().removeBackgroundImage(m_backgroundImage); 0456 m_mainWindow->updateBackgroundImageActionLists(); 0457 m_document->editor()->drawContents(); 0458 } 0459 0460 FitBackgroundImageCommand::FitBackgroundImageCommand(Document *document, QSharedPointer<BackgroundImage> backgroundImage, const QRect &rect) 0461 : QUndoCommand(i18n("Fit Background to Selection")) 0462 , m_document(document) 0463 , m_backgroundImage(backgroundImage) 0464 , m_rect(rect) 0465 { 0466 } 0467 0468 void FitBackgroundImageCommand::redo() 0469 { 0470 m_rect = m_document->backgroundImages().fitBackgroundImage(m_backgroundImage, m_rect); 0471 m_document->editor()->resetSelectionArea(); 0472 m_document->editor()->drawContents(); 0473 } 0474 0475 void FitBackgroundImageCommand::undo() 0476 { 0477 redo(); // same code required 0478 } 0479 0480 ShowBackgroundImageCommand::ShowBackgroundImageCommand(Document *document, QSharedPointer<BackgroundImage> backgroundImage, bool visible) 0481 : QUndoCommand(i18n("Show Background Image")) 0482 , m_document(document) 0483 , m_backgroundImage(backgroundImage) 0484 , m_visible(visible) 0485 { 0486 } 0487 0488 void ShowBackgroundImageCommand::redo() 0489 { 0490 m_visible = m_document->backgroundImages().showBackgroundImage(m_backgroundImage, m_visible); 0491 m_document->editor()->drawContents(); 0492 } 0493 0494 void ShowBackgroundImageCommand::undo() 0495 { 0496 redo(); // same code required 0497 } 0498 0499 RemoveBackgroundImageCommand::RemoveBackgroundImageCommand(Document *document, QSharedPointer<BackgroundImage> backgroundImage, MainWindow *mainWindow) 0500 : QUndoCommand(i18n("Remove Background Image")) 0501 , m_document(document) 0502 , m_backgroundImage(backgroundImage) 0503 , m_mainWindow(mainWindow) 0504 { 0505 } 0506 0507 RemoveBackgroundImageCommand::~RemoveBackgroundImageCommand() 0508 { 0509 // TODO resolve ownership of m_backgroundImage 0510 // delete m_backgroundImage; 0511 // m_backgroundImage may also be deleted by the document, potential for a crash or memory leak 0512 } 0513 0514 void RemoveBackgroundImageCommand::redo() 0515 { 0516 m_document->backgroundImages().removeBackgroundImage(m_backgroundImage); 0517 m_mainWindow->updateBackgroundImageActionLists(); 0518 0519 if (m_backgroundImage->isVisible()) { 0520 m_document->editor()->drawContents(); 0521 } 0522 } 0523 0524 void RemoveBackgroundImageCommand::undo() 0525 { 0526 m_document->backgroundImages().addBackgroundImage(m_backgroundImage); 0527 m_mainWindow->updateBackgroundImageActionLists(); 0528 0529 if (m_backgroundImage->isVisible()) { 0530 m_document->editor()->drawContents(); 0531 } 0532 } 0533 0534 AddDocumentFlossCommand::AddDocumentFlossCommand(Document *document, int key, DocumentFloss *documentFloss, QUndoCommand *parent) 0535 : QUndoCommand(parent) 0536 , m_document(document) 0537 , m_key(key) 0538 , m_documentFloss(documentFloss) 0539 { 0540 } 0541 0542 void AddDocumentFlossCommand::redo() 0543 { 0544 m_document->pattern()->palette().add(m_key, m_documentFloss); 0545 } 0546 0547 void AddDocumentFlossCommand::undo() 0548 { 0549 m_document->pattern()->palette().remove(m_key); 0550 } 0551 0552 RemoveDocumentFlossCommand::RemoveDocumentFlossCommand(Document *document, int key, DocumentFloss *documentFloss, QUndoCommand *parent) 0553 : QUndoCommand(parent) 0554 , m_document(document) 0555 , m_key(key) 0556 , m_documentFloss(documentFloss) 0557 { 0558 } 0559 0560 RemoveDocumentFlossCommand::~RemoveDocumentFlossCommand() 0561 { 0562 delete m_documentFloss; 0563 } 0564 0565 void RemoveDocumentFlossCommand::redo() 0566 { 0567 m_document->pattern()->palette().remove(m_key); 0568 } 0569 0570 void RemoveDocumentFlossCommand::undo() 0571 { 0572 m_document->pattern()->palette().add(m_key, m_documentFloss); 0573 } 0574 0575 ReplaceDocumentFlossCommand::ReplaceDocumentFlossCommand(Document *document, int key, DocumentFloss *documentFloss) 0576 : QUndoCommand() 0577 , m_document(document) 0578 , m_key(key) 0579 , m_documentFloss(documentFloss) 0580 { 0581 } 0582 0583 ReplaceDocumentFlossCommand::~ReplaceDocumentFlossCommand() 0584 { 0585 delete m_documentFloss; 0586 } 0587 0588 void ReplaceDocumentFlossCommand::redo() 0589 { 0590 m_documentFloss = m_document->pattern()->palette().replace(m_key, m_documentFloss); 0591 } 0592 0593 void ReplaceDocumentFlossCommand::undo() 0594 { 0595 redo(); // same code required 0596 } 0597 0598 ClearUnusedFlossesCommand::ClearUnusedFlossesCommand(Document *document) 0599 : QUndoCommand(i18n("Clear Unused Flosses")) 0600 , m_document(document) 0601 { 0602 } 0603 0604 void ClearUnusedFlossesCommand::redo() 0605 { 0606 QUndoCommand::redo(); 0607 m_document->palette()->update(); 0608 } 0609 0610 void ClearUnusedFlossesCommand::undo() 0611 { 0612 QUndoCommand::undo(); 0613 m_document->palette()->update(); 0614 } 0615 0616 ResizeDocumentCommand::ResizeDocumentCommand(Document *document, int width, int height, QUndoCommand *parent) 0617 : QUndoCommand(i18n("Resize Document"), parent) 0618 , m_document(document) 0619 , m_width(width) 0620 , m_height(height) 0621 { 0622 } 0623 0624 void ResizeDocumentCommand::redo() 0625 { 0626 m_originalWidth = m_document->pattern()->stitches().width(); 0627 m_originalHeight = m_document->pattern()->stitches().height(); 0628 QRect extents = m_document->pattern()->stitches().extents(); 0629 int minx = std::min(extents.left(), m_width - extents.width()); 0630 m_xOffset = minx - extents.left(); 0631 int miny = std::min(extents.top(), m_height - extents.height()); 0632 m_yOffset = miny - extents.top(); 0633 m_document->pattern()->stitches().movePattern(m_xOffset, m_yOffset); 0634 m_document->pattern()->stitches().resize(m_width, m_height); 0635 } 0636 0637 void ResizeDocumentCommand::undo() 0638 { 0639 m_document->pattern()->stitches().resize(m_originalWidth, m_originalHeight); 0640 m_document->pattern()->stitches().movePattern(-m_xOffset, -m_yOffset); 0641 } 0642 0643 CropToPatternCommand::CropToPatternCommand(Document *document) 0644 : QUndoCommand(i18n("Crop to Pattern")) 0645 , m_document(document) 0646 { 0647 } 0648 0649 void CropToPatternCommand::redo() 0650 { 0651 m_originalWidth = m_document->pattern()->stitches().width(); 0652 m_originalHeight = m_document->pattern()->stitches().height(); 0653 QRect extents = m_document->pattern()->stitches().extents(); 0654 m_xOffset = -extents.left(); 0655 m_yOffset = -extents.top(); 0656 m_document->pattern()->stitches().movePattern(m_xOffset, m_yOffset); 0657 m_document->pattern()->stitches().resize(extents.width(), extents.height()); 0658 m_document->editor()->readDocumentSettings(); 0659 m_document->preview()->readDocumentSettings(); 0660 } 0661 0662 void CropToPatternCommand::undo() 0663 { 0664 m_document->pattern()->stitches().resize(m_originalWidth, m_originalHeight); 0665 m_document->pattern()->stitches().movePattern(-m_xOffset, -m_yOffset); 0666 m_document->editor()->readDocumentSettings(); 0667 m_document->preview()->readDocumentSettings(); 0668 } 0669 0670 CropToSelectionCommand::CropToSelectionCommand(Document *document, const QRect &selectionArea) 0671 : QUndoCommand(i18n("Crop to Selection")) 0672 , m_document(document) 0673 , m_selectionArea(selectionArea) 0674 { 0675 } 0676 0677 void CropToSelectionCommand::redo() 0678 { 0679 QList<Stitch::Type> maskStitches; 0680 maskStitches << Stitch::TLQtr << Stitch::TRQtr << Stitch::BLQtr << Stitch::BTHalf << Stitch::TL3Qtr << Stitch::BRQtr << Stitch::TBHalf << Stitch::TR3Qtr 0681 << Stitch::BL3Qtr << Stitch::BR3Qtr << Stitch::Full << Stitch::TLSmallHalf << Stitch::TRSmallHalf << Stitch::BLSmallHalf << Stitch::BRSmallHalf 0682 << Stitch::TLSmallFull << Stitch::TRSmallFull << Stitch::BLSmallFull << Stitch::BRSmallFull; 0683 0684 QDataStream stream(&m_originalPattern, QIODevice::WriteOnly); 0685 stream << m_document->pattern()->stitches(); 0686 0687 Pattern *pattern = m_document->pattern()->copy(m_selectionArea, -1, maskStitches, false, false); 0688 m_document->pattern()->stitches().clear(); 0689 m_document->pattern()->stitches().resize(m_selectionArea.width(), m_selectionArea.height()); 0690 m_document->pattern()->paste(pattern, QPoint(0, 0), true); 0691 delete pattern; 0692 0693 m_document->editor()->readDocumentSettings(); 0694 m_document->preview()->readDocumentSettings(); 0695 } 0696 0697 void CropToSelectionCommand::undo() 0698 { 0699 QDataStream stream(&m_originalPattern, QIODevice::ReadOnly); 0700 stream >> m_document->pattern()->stitches(); 0701 m_originalPattern.clear(); 0702 0703 m_document->editor()->readDocumentSettings(); 0704 m_document->preview()->readDocumentSettings(); 0705 } 0706 0707 InsertColumnsCommand::InsertColumnsCommand(Document *document, const QRect &selectionArea) 0708 : QUndoCommand(i18n("Insert Columns")) 0709 , m_document(document) 0710 , m_selectionArea(selectionArea) 0711 { 0712 } 0713 0714 void InsertColumnsCommand::redo() 0715 { 0716 m_document->pattern()->stitches().insertColumns(m_selectionArea.left(), m_selectionArea.width()); 0717 0718 auto backgroundImageIterator = m_document->backgroundImages().backgroundImages(); 0719 0720 while (backgroundImageIterator.hasNext()) { 0721 auto backgroundImage = backgroundImageIterator.next(); 0722 0723 if (backgroundImage->location().left() >= m_selectionArea.left()) { 0724 backgroundImage->setLocation(backgroundImage->location().translated(m_selectionArea.width(), 0)); 0725 } 0726 } 0727 0728 m_document->editor()->readDocumentSettings(); 0729 m_document->preview()->readDocumentSettings(); 0730 } 0731 0732 void InsertColumnsCommand::undo() 0733 { 0734 m_document->pattern()->stitches().removeColumns(m_selectionArea.left(), m_selectionArea.width()); 0735 0736 auto backgroundImageIterator = m_document->backgroundImages().backgroundImages(); 0737 0738 while (backgroundImageIterator.hasNext()) { 0739 auto backgroundImage = backgroundImageIterator.next(); 0740 0741 if (backgroundImage->location().left() > m_selectionArea.left()) { 0742 backgroundImage->setLocation(backgroundImage->location().translated(-m_selectionArea.width(), 0)); 0743 } 0744 } 0745 0746 m_document->editor()->readDocumentSettings(); 0747 m_document->preview()->readDocumentSettings(); 0748 } 0749 0750 InsertRowsCommand::InsertRowsCommand(Document *document, const QRect &selectionArea) 0751 : QUndoCommand(i18n("Insert Rows")) 0752 , m_document(document) 0753 , m_selectionArea(selectionArea) 0754 { 0755 } 0756 0757 void InsertRowsCommand::redo() 0758 { 0759 m_document->pattern()->stitches().insertRows(m_selectionArea.top(), m_selectionArea.height()); 0760 0761 auto backgroundImageIterator = m_document->backgroundImages().backgroundImages(); 0762 0763 while (backgroundImageIterator.hasNext()) { 0764 auto backgroundImage = backgroundImageIterator.next(); 0765 0766 if (backgroundImage->location().top() >= m_selectionArea.top()) { 0767 backgroundImage->setLocation(backgroundImage->location().translated(0, m_selectionArea.height())); 0768 } 0769 } 0770 0771 m_document->editor()->readDocumentSettings(); 0772 m_document->preview()->readDocumentSettings(); 0773 } 0774 0775 void InsertRowsCommand::undo() 0776 { 0777 m_document->pattern()->stitches().removeRows(m_selectionArea.top(), m_selectionArea.height()); 0778 0779 auto backgroundImageIterator = m_document->backgroundImages().backgroundImages(); 0780 0781 while (backgroundImageIterator.hasNext()) { 0782 auto backgroundImage = backgroundImageIterator.next(); 0783 0784 if (backgroundImage->location().top() > m_selectionArea.top()) { 0785 backgroundImage->setLocation(backgroundImage->location().translated(0, -m_selectionArea.height())); 0786 } 0787 } 0788 0789 m_document->editor()->readDocumentSettings(); 0790 m_document->preview()->readDocumentSettings(); 0791 } 0792 0793 ExtendPatternCommand::ExtendPatternCommand(Document *document, int top, int left, int right, int bottom) 0794 : QUndoCommand(i18n("Extend Pattern")) 0795 , m_document(document) 0796 , m_top(top) 0797 , m_left(left) 0798 , m_right(right) 0799 , m_bottom(bottom) 0800 { 0801 } 0802 0803 void ExtendPatternCommand::redo() 0804 { 0805 StitchData &stitchData = m_document->pattern()->stitches(); 0806 stitchData.resize(stitchData.width() + m_left + m_right, stitchData.height() + m_top + m_bottom); 0807 stitchData.movePattern(m_left, m_top); 0808 auto backgroundImageIterator = m_document->backgroundImages().backgroundImages(); 0809 0810 while (backgroundImageIterator.hasNext()) { 0811 auto backgroundImage = backgroundImageIterator.next(); 0812 backgroundImage->setLocation(backgroundImage->location().translated(m_left, m_top)); 0813 } 0814 0815 m_document->editor()->readDocumentSettings(); 0816 m_document->preview()->readDocumentSettings(); 0817 } 0818 0819 void ExtendPatternCommand::undo() 0820 { 0821 StitchData &stitchData = m_document->pattern()->stitches(); 0822 stitchData.movePattern(-m_left, -m_top); 0823 stitchData.resize(stitchData.width() - m_left - m_right, stitchData.height() - m_top - m_bottom); 0824 auto backgroundImageIterator = m_document->backgroundImages().backgroundImages(); 0825 0826 while (backgroundImageIterator.hasNext()) { 0827 auto backgroundImage = backgroundImageIterator.next(); 0828 backgroundImage->setLocation(backgroundImage->location().translated(-m_left, -m_top)); 0829 } 0830 0831 m_document->editor()->readDocumentSettings(); 0832 m_document->preview()->readDocumentSettings(); 0833 } 0834 0835 CentrePatternCommand::CentrePatternCommand(Document *document) 0836 : QUndoCommand(i18n("Center Pattern")) 0837 , m_document(document) 0838 { 0839 } 0840 0841 void CentrePatternCommand::redo() 0842 { 0843 QRect extents = m_document->pattern()->stitches().extents(); 0844 0845 m_xOffset = ((m_document->pattern()->stitches().width() - extents.width()) / 2) - extents.left(); 0846 m_yOffset = ((m_document->pattern()->stitches().height() - extents.height()) / 2) - extents.top(); 0847 0848 if (m_xOffset || m_yOffset) { 0849 m_document->pattern()->stitches().movePattern(m_xOffset, m_yOffset); 0850 0851 m_document->editor()->drawContents(); 0852 m_document->preview()->drawContents(); 0853 } 0854 } 0855 0856 void CentrePatternCommand::undo() 0857 { 0858 if (m_xOffset || m_yOffset) { 0859 m_document->pattern()->stitches().movePattern(-m_xOffset, -m_yOffset); 0860 0861 m_document->editor()->drawContents(); 0862 m_document->preview()->drawContents(); 0863 } 0864 } 0865 0866 UpdateDocumentPaletteCommand::UpdateDocumentPaletteCommand(Document *document, const DocumentPalette &palette) 0867 : QUndoCommand(i18n("Update Palette")) 0868 , m_document(document) 0869 , m_palette(palette) 0870 { 0871 } 0872 0873 void UpdateDocumentPaletteCommand::redo() 0874 { 0875 DocumentPalette palette = m_document->pattern()->palette(); 0876 m_document->pattern()->palette() = m_palette; 0877 m_palette = palette; 0878 0879 m_document->editor()->drawContents(); 0880 m_document->preview()->drawContents(); 0881 m_document->palette()->update(); 0882 } 0883 0884 void UpdateDocumentPaletteCommand::undo() 0885 { 0886 redo(); // swaps the palette back 0887 } 0888 0889 ChangeSchemeCommand::ChangeSchemeCommand(Document *document, const QString &schemeName, QUndoCommand *parent) 0890 : QUndoCommand(i18n("Change Floss Scheme"), parent) 0891 , m_document(document) 0892 , m_schemeName(schemeName) 0893 { 0894 } 0895 0896 void ChangeSchemeCommand::redo() 0897 { 0898 QDataStream stream(&m_originalPalette, QIODevice::WriteOnly); 0899 stream << m_document->pattern()->palette(); 0900 m_document->pattern()->palette().setSchemeName(m_schemeName); 0901 0902 m_document->editor()->drawContents(); 0903 m_document->preview()->drawContents(); 0904 m_document->palette()->update(); 0905 } 0906 0907 void ChangeSchemeCommand::undo() 0908 { 0909 QDataStream stream(&m_originalPalette, QIODevice::ReadOnly); 0910 stream >> m_document->pattern()->palette(); 0911 m_originalPalette.clear(); 0912 0913 m_document->editor()->drawContents(); 0914 m_document->preview()->drawContents(); 0915 m_document->palette()->update(); 0916 } 0917 0918 EditorReadDocumentSettingsCommand::EditorReadDocumentSettingsCommand(Editor *editor) 0919 : QUndoCommand() 0920 , m_editor(editor) 0921 { 0922 } 0923 0924 void EditorReadDocumentSettingsCommand::redo() 0925 { 0926 m_editor->readDocumentSettings(); 0927 } 0928 0929 void EditorReadDocumentSettingsCommand::undo() 0930 { 0931 redo(); // same code required 0932 } 0933 0934 PreviewReadDocumentSettingsCommand::PreviewReadDocumentSettingsCommand(Preview *preview) 0935 : QUndoCommand() 0936 , m_preview(preview) 0937 { 0938 } 0939 0940 void PreviewReadDocumentSettingsCommand::redo() 0941 { 0942 m_preview->readDocumentSettings(); 0943 } 0944 0945 void PreviewReadDocumentSettingsCommand::undo() 0946 { 0947 redo(); // same code required 0948 } 0949 0950 PaletteReplaceColorCommand::PaletteReplaceColorCommand(Document *document, int originalIndex, int replacementIndex) 0951 : QUndoCommand(i18n("Replace Color")) 0952 , m_document(document) 0953 , m_originalIndex(originalIndex) 0954 , m_replacementIndex(replacementIndex) 0955 { 0956 } 0957 0958 void PaletteReplaceColorCommand::redo() 0959 { 0960 if (m_stitches.count() || m_backstitches.count() || m_knots.count()) { 0961 // populated from a previous redo call 0962 // iterator over the existing pointers 0963 for (Stitch *stitch : m_stitches) { 0964 stitch->colorIndex = m_replacementIndex; 0965 } 0966 0967 for (Backstitch *backstitch : m_backstitches) { 0968 backstitch->colorIndex = m_replacementIndex; 0969 } 0970 0971 for (Knot *knot : m_knots) { 0972 knot->colorIndex = m_replacementIndex; 0973 } 0974 } else { 0975 // search the stitch data for stitches of the required color 0976 StitchData &stitchData = m_document->pattern()->stitches(); 0977 0978 for (int row = 0; row < stitchData.height(); ++row) { 0979 for (int col = 0; col < stitchData.width(); ++col) { 0980 StitchQueue *queue = stitchData.stitchQueueAt(QPoint(col, row)); 0981 0982 if (queue) { 0983 QListIterator<Stitch *> stitchIterator(*queue); 0984 0985 while (stitchIterator.hasNext()) { 0986 Stitch *stitch = stitchIterator.next(); 0987 0988 if (stitch->colorIndex == m_originalIndex) { 0989 m_stitches.append(stitch); 0990 stitch->colorIndex = m_replacementIndex; 0991 } 0992 } 0993 } 0994 } 0995 } 0996 0997 QListIterator<Backstitch *> backstitchIterator = stitchData.backstitchIterator(); 0998 0999 while (backstitchIterator.hasNext()) { 1000 Backstitch *backstitch = backstitchIterator.next(); 1001 1002 if (backstitch->colorIndex == m_originalIndex) { 1003 m_backstitches.append(backstitch); 1004 backstitch->colorIndex = m_replacementIndex; 1005 } 1006 } 1007 1008 QListIterator<Knot *> knotIterator = stitchData.knotIterator(); 1009 1010 while (knotIterator.hasNext()) { 1011 Knot *knot = knotIterator.next(); 1012 1013 if (knot->colorIndex == m_originalIndex) { 1014 m_knots.append(knot); 1015 knot->colorIndex = m_replacementIndex; 1016 } 1017 } 1018 } 1019 1020 m_document->editor()->drawContents(); 1021 m_document->preview()->drawContents(); 1022 m_document->palette()->update(); 1023 } 1024 1025 void PaletteReplaceColorCommand::undo() 1026 { 1027 QListIterator<Stitch *> stitchIterator(m_stitches); 1028 1029 while (stitchIterator.hasNext()) { 1030 stitchIterator.next()->colorIndex = m_originalIndex; 1031 } 1032 1033 QListIterator<Backstitch *> backstitchIterator(m_backstitches); 1034 1035 while (backstitchIterator.hasNext()) { 1036 backstitchIterator.next()->colorIndex = m_originalIndex; 1037 } 1038 1039 QListIterator<Knot *> knotIterator(m_knots); 1040 1041 while (knotIterator.hasNext()) { 1042 knotIterator.next()->colorIndex = m_originalIndex; 1043 } 1044 1045 m_document->editor()->drawContents(); 1046 m_document->preview()->drawContents(); 1047 m_document->palette()->update(); 1048 } 1049 1050 PaletteSwapColorCommand::PaletteSwapColorCommand(Document *document, int originalIndex, int swappedIndex) 1051 : QUndoCommand(i18n("Swap Colors")) 1052 , m_document(document) 1053 , m_originalIndex(originalIndex) 1054 , m_swappedIndex(swappedIndex) 1055 { 1056 } 1057 1058 void PaletteSwapColorCommand::redo() 1059 { 1060 m_document->pattern()->palette().swap(m_originalIndex, m_swappedIndex); 1061 m_document->editor()->drawContents(); 1062 m_document->preview()->drawContents(); 1063 m_document->palette()->update(); 1064 } 1065 1066 void PaletteSwapColorCommand::undo() 1067 { 1068 redo(); 1069 } 1070 1071 UpdatePrinterConfigurationCommand::UpdatePrinterConfigurationCommand(Document *document, const PrinterConfiguration &printerConfiguration) 1072 : QUndoCommand(i18n("Update Printer Configuration")) 1073 , m_document(document) 1074 , m_printerConfiguration(printerConfiguration) 1075 { 1076 } 1077 1078 void UpdatePrinterConfigurationCommand::redo() 1079 { 1080 PrinterConfiguration original = m_document->printerConfiguration(); 1081 m_document->setPrinterConfiguration(m_printerConfiguration); 1082 m_printerConfiguration = original; 1083 } 1084 1085 void UpdatePrinterConfigurationCommand::undo() 1086 { 1087 redo(); 1088 } 1089 1090 EditCutCommand::EditCutCommand(Document *document, 1091 const QRect &selectionArea, 1092 int colorMask, 1093 const QList<Stitch::Type> &stitchMasks, 1094 bool excludeBackstitches, 1095 bool excludeKnots) 1096 : QUndoCommand(i18n("Cut")) 1097 , m_document(document) 1098 , m_selectionArea(selectionArea) 1099 , m_colorMask(colorMask) 1100 , m_stitchMasks(stitchMasks) 1101 , m_excludeBackstitches(excludeBackstitches) 1102 , m_excludeKnots(excludeKnots) 1103 , m_originalPattern(nullptr) 1104 { 1105 } 1106 1107 EditCutCommand::~EditCutCommand() 1108 { 1109 delete m_originalPattern; 1110 } 1111 1112 void EditCutCommand::redo() 1113 { 1114 m_originalPattern = m_document->pattern()->cut(m_selectionArea, m_colorMask, m_stitchMasks, m_excludeBackstitches, m_excludeKnots); 1115 1116 QByteArray data; 1117 QDataStream stream(&data, QIODevice::WriteOnly); 1118 stream << *m_originalPattern; 1119 1120 QMimeData *mimeData = new QMimeData(); 1121 mimeData->setData(QStringLiteral("application/kxstitch"), data); 1122 1123 QApplication::clipboard()->setMimeData(mimeData); 1124 1125 m_document->editor()->drawContents(); 1126 m_document->preview()->drawContents(); 1127 } 1128 1129 void EditCutCommand::undo() 1130 { 1131 m_document->pattern()->paste(m_originalPattern, m_selectionArea.topLeft(), true); 1132 delete m_originalPattern; 1133 m_originalPattern = nullptr; 1134 1135 m_document->editor()->drawContents(); 1136 m_document->preview()->drawContents(); 1137 } 1138 1139 EditPasteCommand::EditPasteCommand(Document *document, Pattern *pattern, const QPoint &cell, bool merge, const QString &source) 1140 : QUndoCommand(source) 1141 , m_document(document) 1142 , m_pastePattern(pattern) 1143 , m_cell(cell) 1144 , m_merge(merge) 1145 { 1146 } 1147 1148 void EditPasteCommand::redo() 1149 { 1150 QDataStream stream(&m_originalPattern, QIODevice::WriteOnly); 1151 stream << *(m_document->pattern()); 1152 m_document->pattern()->paste(m_pastePattern, m_cell, m_merge); 1153 1154 m_document->editor()->drawContents(); 1155 m_document->preview()->drawContents(); 1156 m_document->palette()->update(); 1157 } 1158 1159 void EditPasteCommand::undo() 1160 { 1161 QDataStream stream(&m_originalPattern, QIODevice::ReadOnly); 1162 m_document->pattern()->clear(); 1163 stream >> *(m_document->pattern()); 1164 m_originalPattern.clear(); 1165 1166 m_document->editor()->drawContents(); 1167 m_document->preview()->drawContents(); 1168 m_document->palette()->update(); 1169 } 1170 1171 MirrorSelectionCommand::MirrorSelectionCommand(Document *document, 1172 const QRect &selectionArea, 1173 int colorMask, 1174 const QList<Stitch::Type> &stitchMasks, 1175 bool excludeBackstitches, 1176 bool excludeKnots, 1177 Qt::Orientation orientation, 1178 bool copies, 1179 const QByteArray &originalPatternData, 1180 Pattern *invertedPattern, 1181 const QPoint &pasteCell, 1182 bool merge) 1183 : QUndoCommand(i18n("Mirror Selection")) 1184 , m_document(document) 1185 , m_selectionArea(selectionArea) 1186 , m_colorMask(colorMask) 1187 , m_stitchMasks(stitchMasks) 1188 , m_excludeBackstitches(excludeBackstitches) 1189 , m_excludeKnots(excludeKnots) 1190 , m_orientation(orientation) 1191 , m_copies(copies) 1192 , m_originalPatternData(originalPatternData) 1193 , m_invertedPattern(invertedPattern) 1194 , m_pasteCell(pasteCell) 1195 , m_merge(merge) 1196 { 1197 } 1198 1199 MirrorSelectionCommand::~MirrorSelectionCommand() 1200 { 1201 delete m_invertedPattern; 1202 } 1203 1204 void MirrorSelectionCommand::redo() 1205 { 1206 if (!m_copies) { 1207 delete m_document->pattern()->cut(m_selectionArea, m_colorMask, m_stitchMasks, m_excludeBackstitches, m_excludeKnots); 1208 } 1209 1210 m_document->pattern()->paste(m_invertedPattern, m_pasteCell, m_merge); 1211 1212 m_document->editor()->drawContents(); 1213 m_document->preview()->drawContents(); 1214 } 1215 1216 void MirrorSelectionCommand::undo() 1217 { 1218 m_document->pattern()->stitches().clear(); 1219 QDataStream stream(&m_originalPatternData, QIODevice::ReadOnly); 1220 stream >> m_document->pattern()->stitches(); 1221 1222 m_document->editor()->drawContents(); 1223 m_document->preview()->drawContents(); 1224 } 1225 1226 RotateSelectionCommand::RotateSelectionCommand(Document *document, 1227 const QRect &selectionArea, 1228 int colorMask, 1229 const QList<Stitch::Type> &stitchMasks, 1230 bool excludeBackstitches, 1231 bool excludeKnots, 1232 StitchData::Rotation rotation, 1233 bool copies, 1234 const QByteArray &originalPatternData, 1235 Pattern *rotatedPattern, 1236 const QPoint &pasteCell, 1237 bool merge) 1238 : QUndoCommand(i18n("Rotate Selection")) 1239 , m_document(document) 1240 , m_selectionArea(selectionArea) 1241 , m_colorMask(colorMask) 1242 , m_stitchMasks(stitchMasks) 1243 , m_excludeBackstitches(excludeBackstitches) 1244 , m_excludeKnots(excludeKnots) 1245 , m_rotation(rotation) 1246 , m_copies(copies) 1247 , m_originalPatternData(originalPatternData) 1248 , m_rotatedPattern(rotatedPattern) 1249 , m_pasteCell(pasteCell) 1250 , m_merge(merge) 1251 { 1252 } 1253 1254 RotateSelectionCommand::~RotateSelectionCommand() 1255 { 1256 delete m_rotatedPattern; 1257 } 1258 1259 void RotateSelectionCommand::redo() 1260 { 1261 if (!m_copies) { 1262 delete m_document->pattern()->cut(m_selectionArea, m_colorMask, m_stitchMasks, m_excludeBackstitches, m_excludeKnots); 1263 } 1264 1265 m_document->pattern()->paste(m_rotatedPattern, m_pasteCell, m_merge); 1266 1267 m_document->editor()->drawContents(); 1268 m_document->preview()->drawContents(); 1269 } 1270 1271 void RotateSelectionCommand::undo() 1272 { 1273 m_document->pattern()->stitches().clear(); 1274 QDataStream stream(&m_originalPatternData, QIODevice::ReadOnly); 1275 stream >> m_document->pattern()->stitches(); 1276 1277 m_document->editor()->drawContents(); 1278 m_document->preview()->drawContents(); 1279 } 1280 1281 AlphabetCommand::AlphabetCommand(Document *document) 1282 : QUndoCommand(i18n("Alphabet")) 1283 , m_document(document) 1284 { 1285 } 1286 1287 AlphabetCommand::~AlphabetCommand() 1288 { 1289 qDeleteAll(m_children); 1290 } 1291 1292 void AlphabetCommand::redo() 1293 { 1294 for (int i = 0; i < m_children.size(); ++i) { 1295 m_children.at(i)->redo(); 1296 } 1297 } 1298 1299 void AlphabetCommand::undo() 1300 { 1301 for (int i = m_children.size() - 1; i >= 0; --i) { 1302 m_children.at(i)->undo(); 1303 } 1304 } 1305 1306 void AlphabetCommand::push(QUndoCommand *child) 1307 { 1308 m_children.append(child); 1309 child->redo(); 1310 } 1311 1312 QUndoCommand *AlphabetCommand::pop() 1313 { 1314 if (m_children.isEmpty()) { 1315 return nullptr; 1316 } 1317 1318 m_children.last()->undo(); 1319 return m_children.takeLast(); 1320 } 1321 1322 int AlphabetCommand::childCount() const 1323 { 1324 return m_children.count(); 1325 } 1326 1327 ConfigurationCommand::ConfigurationCommand(MainWindow *mainWindow) 1328 : QUndoCommand(i18n("Configure KXStitch")) 1329 , m_mainWindow(mainWindow) 1330 { 1331 } 1332 1333 void ConfigurationCommand::redo() 1334 { 1335 QUndoCommand::redo(); 1336 m_mainWindow->loadSettings(); 1337 } 1338 1339 void ConfigurationCommand::undo() 1340 { 1341 QUndoCommand::undo(); 1342 m_mainWindow->loadSettings(); 1343 }