File indexing completed on 2024-05-05 14:26:28
0001 /* 0002 This file is part of the Okteta Core library, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2008 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "piecetablechangehistory.hpp" 0010 0011 // lib 0012 #include "grouppiecetablechange.hpp" 0013 // 0014 #include <addressrangelist.hpp> 0015 #include <arraychangemetricslist.hpp> 0016 0017 namespace KPieceTable { 0018 0019 void PieceTableChangeHistory::clear() 0020 { 0021 while (!mChangeStack.isEmpty()) { 0022 delete mChangeStack.pop(); 0023 } 0024 0025 mTryToMergeAppendedChange = false; 0026 mAppliedChangesCount = 0; 0027 mBaseBeforeChangeIndex = 0; 0028 mAppliedChangesDataSize = 0; 0029 0030 mActiveGroupChange = nullptr; 0031 } 0032 0033 void PieceTableChangeHistory::getChangeData(ArrayChangeMetrics* metrics, Address* storageOffset, 0034 int versionIndex) const 0035 { 0036 AbstractPieceTableChange* change = mChangeStack.at(versionIndex); 0037 *metrics = change->metrics(); 0038 *storageOffset = change->storageOffset(); 0039 } 0040 0041 void PieceTableChangeHistory::setBeforeCurrentChangeAsBase(bool hide) 0042 { 0043 mBaseBeforeChangeIndex = hide ? -1 : mAppliedChangesCount; 0044 mTryToMergeAppendedChange = false; 0045 } 0046 0047 void PieceTableChangeHistory::openGroupedChange(const QString& description) 0048 { 0049 auto* groupChange = new GroupPieceTableChange(mActiveGroupChange, description); 0050 0051 appendChange(groupChange); 0052 mActiveGroupChange = groupChange; 0053 } 0054 0055 void PieceTableChangeHistory::closeGroupedChange(const QString& description) 0056 { 0057 if (mActiveGroupChange) { 0058 if (!description.isEmpty()) { 0059 mActiveGroupChange->setDescription(description); 0060 } 0061 mActiveGroupChange = mActiveGroupChange->parent(); 0062 } 0063 } 0064 0065 void PieceTableChangeHistory::finishChange() 0066 { 0067 if (mActiveGroupChange) { 0068 mActiveGroupChange->finishChange(); 0069 } else { 0070 mTryToMergeAppendedChange = false; 0071 } 0072 } 0073 0074 bool PieceTableChangeHistory::appendChange(AbstractPieceTableChange* change) 0075 { 0076 // chop unapplied changes 0077 if (mAppliedChangesCount < mChangeStack.size()) { 0078 // hide baseindex if needed 0079 if (mBaseBeforeChangeIndex > mAppliedChangesCount) { 0080 mBaseBeforeChangeIndex = -1; 0081 } 0082 do { 0083 AbstractPieceTableChange* droppedChange = mChangeStack.pop(); 0084 delete droppedChange; 0085 } while (mAppliedChangesCount < mChangeStack.size()); 0086 } 0087 0088 mAppliedChangesDataSize += change->dataSize(); 0089 0090 bool isNotMerged = true; 0091 if (mActiveGroupChange) { 0092 mActiveGroupChange->appendChange(change); 0093 isNotMerged = false; // TODO: hack for as long as subgroups are not undoable 0094 } else { 0095 if (mTryToMergeAppendedChange && mAppliedChangesCount > 0) { 0096 isNotMerged = !mChangeStack.top()->merge(change); 0097 } else { 0098 mTryToMergeAppendedChange = true; 0099 } 0100 0101 if (isNotMerged) { 0102 mChangeStack.push(change); 0103 ++mAppliedChangesCount; 0104 } else { 0105 delete change; 0106 } 0107 } 0108 0109 return isNotMerged; 0110 } 0111 0112 bool PieceTableChangeHistory::revertBeforeChange(PieceTable* pieceTable, int changeId, 0113 AddressRangeList* changedRanges, 0114 ArrayChangeMetricsList* changeList) 0115 { 0116 int currentChangeId = mAppliedChangesCount; 0117 0118 if (currentChangeId == changeId) { 0119 return false; 0120 } 0121 0122 // close any grouped changes 0123 while (mActiveGroupChange) { 0124 mActiveGroupChange = mActiveGroupChange->parent(); 0125 } 0126 0127 if (currentChangeId < changeId) { 0128 for (; currentChangeId < changeId; ++currentChangeId) { 0129 const AbstractPieceTableChange* change = mChangeStack[currentChangeId]; 0130 0131 if (change->type() == AbstractPieceTableChange::GroupId) { 0132 const auto* groupChange = static_cast<const GroupPieceTableChange*>(change); 0133 const AddressRangeList changedRangeList = groupChange->applyGroup(pieceTable); 0134 changedRanges->addAddressRangeList(changedRangeList); 0135 0136 const QVector<ArrayChangeMetrics> changeMetricsList = groupChange->groupMetrics(); 0137 *changeList += changeMetricsList; 0138 } else { 0139 const AddressRange changedRange = change->apply(pieceTable); 0140 changedRanges->addAddressRange(changedRange); 0141 0142 const ArrayChangeMetrics changeMetrics = change->metrics(); 0143 changeList->append(changeMetrics); 0144 } 0145 0146 mAppliedChangesDataSize += change->dataSize(); 0147 } 0148 } else { 0149 for (--currentChangeId; changeId <= currentChangeId; --currentChangeId) { 0150 const AbstractPieceTableChange* change = mChangeStack[currentChangeId]; 0151 0152 if (change->type() == AbstractPieceTableChange::GroupId) { 0153 const auto* groupChange = static_cast<const GroupPieceTableChange*>(change); 0154 const AddressRangeList changedRangeList = groupChange->revertGroup(pieceTable); 0155 changedRanges->addAddressRangeList(changedRangeList); 0156 0157 const QVector<ArrayChangeMetrics> changeMetricsList = groupChange->groupMetrics(true); 0158 *changeList += changeMetricsList; 0159 } else { 0160 const AddressRange changedRange = change->revert(pieceTable); 0161 changedRanges->addAddressRange(changedRange); 0162 0163 ArrayChangeMetrics changeMetrics = change->metrics(); 0164 changeMetrics.revert(); 0165 changeList->append(changeMetrics); 0166 } 0167 mAppliedChangesDataSize -= change->dataSize(); 0168 } 0169 } 0170 mAppliedChangesCount = changeId; 0171 mTryToMergeAppendedChange = false; 0172 0173 return true; 0174 } 0175 0176 }