File indexing completed on 2025-02-23 04:08:58
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_change_guides_command.h" 0008 0009 #include "kis_guides_config.h" 0010 #include "KisDocument.h" 0011 #include <kis_image.h> 0012 0013 #include <QList> 0014 #include <QListIterator> 0015 0016 struct KisChangeGuidesCommand::Private 0017 { 0018 Private(KisDocument *_doc, KisChangeGuidesCommand *q) : doc(_doc), q(q), firstRedo(true) {} 0019 0020 bool sameOrOnlyMovedOneGuideBetween(const KisGuidesConfig &first, const KisGuidesConfig &second); 0021 enum Status { 0022 NO_DIFF = 0, 0023 ONE_DIFF = 1, 0024 ADDITION = 4, 0025 REMOVAL = 16, 0026 OTHER_DIFF = 1024 0027 }; 0028 Status diff(const QList<qreal> &first, const QList<qreal> &second); 0029 0030 void switchTo(const KisGuidesConfig &config); 0031 0032 KisDocument *doc; 0033 KisChangeGuidesCommand *q; 0034 0035 KisGuidesConfig oldGuides; 0036 KisGuidesConfig newGuides; 0037 0038 bool firstRedo; 0039 }; 0040 0041 bool KisChangeGuidesCommand::Private::sameOrOnlyMovedOneGuideBetween(const KisGuidesConfig &first, const KisGuidesConfig &second) 0042 { 0043 int ret = diff(first.horizontalGuideLines(), second.horizontalGuideLines()) + 0044 diff(first.verticalGuideLines(), second.verticalGuideLines()); 0045 0046 if (ret == ADDITION) { 0047 q->setText(kundo2_i18n("Add Guide")); 0048 } else if (ret == REMOVAL) { 0049 q->setText(kundo2_i18n("Remove Guide")); 0050 } else if (ret == NO_DIFF || ret == ONE_DIFF) { // meaning we will still merge it 0051 // XXX: how to deal with NO_DIFF (the command "should" be removed -- how?) 0052 q->setText(kundo2_i18n("Edit Guides")); 0053 } else { 0054 return false; 0055 } 0056 return true; 0057 } 0058 0059 KisChangeGuidesCommand::Private::Status KisChangeGuidesCommand::Private::diff(const QList<qreal> &first, const QList<qreal> &second) 0060 { 0061 if (first.size() == second.size()) { 0062 int diffCount = 0; 0063 for (int i = 0; i < first.size(); ++i) { 0064 if (first[i] != second[i]) { 0065 ++diffCount; 0066 if (diffCount > 1) { 0067 return OTHER_DIFF; 0068 } 0069 } 0070 } 0071 return diffCount == 0 ? NO_DIFF : ONE_DIFF; 0072 } else if (first.size() - second.size() == -1) { // added a guide 0073 QList<qreal> beforeRemoval = second; 0074 beforeRemoval.takeLast(); 0075 return first == beforeRemoval ? ADDITION : OTHER_DIFF; 0076 } else if (first.size() - second.size() == 1) { // removed a guide 0077 bool skippedItem = false; 0078 for (QListIterator<qreal> i(first), j(second); i.hasNext() && j.hasNext(); ) { 0079 qreal curFirst = i.next(); 0080 qreal curSecond = j.next(); 0081 if (!skippedItem && curFirst != curSecond) { 0082 curFirst = i.next(); // try to go to the next item and see if it matches 0083 } 0084 if (curFirst != curSecond) { 0085 return OTHER_DIFF; 0086 } 0087 } 0088 // here we conclude only one guide is removed 0089 return REMOVAL; 0090 } else { 0091 return OTHER_DIFF; 0092 } 0093 } 0094 0095 void KisChangeGuidesCommand::Private::switchTo(const KisGuidesConfig &config) 0096 { 0097 KisGuidesConfig curConfig = doc->guidesConfig(); 0098 curConfig.setHorizontalGuideLines(config.horizontalGuideLines()); 0099 curConfig.setVerticalGuideLines(config.verticalGuideLines()); 0100 doc->setGuidesConfig(curConfig); 0101 } 0102 0103 KisChangeGuidesCommand::KisChangeGuidesCommand(KisDocument *doc, const KisGuidesConfig &oldGuides, const KisGuidesConfig &newGuides) 0104 : KUndo2Command(kundo2_i18n("Edit Guides")), 0105 m_d(new Private(doc, this)) 0106 { 0107 m_d->oldGuides = oldGuides; 0108 m_d->newGuides = newGuides; 0109 // update the undo command text 0110 m_d->sameOrOnlyMovedOneGuideBetween(m_d->oldGuides, m_d->newGuides); 0111 } 0112 0113 KisChangeGuidesCommand::~KisChangeGuidesCommand() 0114 { 0115 } 0116 0117 void KisChangeGuidesCommand::undo() 0118 { 0119 m_d->switchTo(m_d->oldGuides); 0120 } 0121 0122 void KisChangeGuidesCommand::redo() 0123 { 0124 if (m_d->firstRedo) { 0125 m_d->firstRedo = false; 0126 return; 0127 } 0128 m_d->switchTo(m_d->newGuides); 0129 } 0130 0131 int KisChangeGuidesCommand::id() const 0132 { 0133 return 1863; 0134 } 0135