1 /* 2 SPDX-FileCopyrightText: 2001-2004,2009 Otto Bruggeman <bruggie@gmail.com> 3 SPDX-FileCopyrightText: 2001-2003 John Firebaugh <jfirebaugh@kde.org> 4 5 SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 8 #ifndef DIFFERENCE_H 9 #define DIFFERENCE_H 10 11 #include <QVector> 12 #include <QObject> 13 14 #include "diff2_export.h" 15 #include "marker.h" 16 17 // #include <komparediffdebug.h> 18 19 class QString; 20 21 namespace Diff2 22 { 23 24 /** 25 * A difference string. 26 */ 27 class DIFF2_EXPORT DifferenceString 28 { 29 public: DifferenceString()30 DifferenceString() 31 { 32 // qCDebug(LIBKOMPAREDIFF2) << "DifferenceString::DifferenceString()"; 33 } 34 explicit DifferenceString(const QString& string, const MarkerList& markerList = MarkerList()) : m_string(string)35 m_string(string), 36 m_markerList(markerList) 37 { 38 // qCDebug(LIBKOMPAREDIFF2) << "DifferenceString::DifferenceString( " << string << ", " << markerList << " )"; 39 calculateHash(); 40 } DifferenceString(const DifferenceString & ds)41 DifferenceString(const DifferenceString& ds) : 42 m_string(ds.m_string), 43 m_conflict(ds.m_conflict), 44 m_hash(ds.m_hash), 45 m_markerList(ds.m_markerList) 46 { 47 // qCDebug(LIBKOMPAREDIFF2) << "DifferenceString::DifferenceString( const DifferenceString& " << ds << " )"; 48 } ~DifferenceString()49 ~DifferenceString() 50 { 51 qDeleteAll(m_markerList); 52 } 53 54 public: string()55 const QString& string() const 56 { 57 return m_string; 58 } conflictString()59 const QString& conflictString() const 60 { 61 return m_conflict; 62 } markerList()63 const MarkerList& markerList() 64 { 65 return m_markerList; 66 } setString(const QString & string)67 void setString(const QString& string) 68 { 69 m_string = string; 70 calculateHash(); 71 } setConflictString(const QString & conflict)72 void setConflictString(const QString& conflict) 73 { 74 m_conflict = conflict; 75 } setMarkerList(const MarkerList & markerList)76 void setMarkerList(const MarkerList& markerList) 77 { 78 m_markerList = markerList; 79 } prepend(Marker * marker)80 void prepend(Marker* marker) 81 { 82 m_markerList.prepend(marker); 83 } 84 bool operator==(const DifferenceString& ks) 85 { 86 if (m_hash != ks.m_hash) 87 return false; 88 return m_string == ks.m_string; 89 } 90 91 protected: calculateHash()92 void calculateHash() 93 { 94 unsigned short const* str = reinterpret_cast<unsigned short const*>(m_string.unicode()); 95 const unsigned int len = m_string.length(); 96 97 m_hash = 1315423911; 98 99 for (unsigned int i = 0; i < len; ++i) 100 { 101 m_hash ^= (m_hash << 5) + str[i] + (m_hash >> 2); 102 } 103 } 104 105 private: 106 QString m_string; 107 QString m_conflict; 108 unsigned int m_hash; 109 MarkerList m_markerList; 110 }; 111 112 using DifferenceStringList = QVector<DifferenceString*>; 113 using DifferenceStringListIterator = QVector<DifferenceString*>::iterator; 114 using DifferenceStringListConstIterator = QVector<DifferenceString*>::const_iterator; 115 116 /** 117 * A difference. 118 */ 119 class DIFF2_EXPORT Difference : public QObject 120 { 121 Q_OBJECT 122 public: 123 enum Type { Change, Insert, Delete, Unchanged }; 124 125 public: 126 Difference(int sourceLineNo, int destinationLineNo, int type = Difference::Unchanged); 127 ~Difference() override; 128 129 public: type()130 int type() const { return m_type; }; 131 sourceLineNumber()132 int sourceLineNumber() const { return m_sourceLineNo; } destinationLineNumber()133 int destinationLineNumber() const { return m_destinationLineNo; } 134 135 int sourceLineCount() const; 136 int destinationLineCount() const; 137 138 int sourceLineEnd() const; 139 int destinationLineEnd() const; 140 141 /// Destination line number that tracks applying/unapplying of other differences 142 /// Essentially a line number in a patch consisting of applied diffs only trackingDestinationLineNumber()143 int trackingDestinationLineNumber() const { return m_trackingDestinationLineNo; } 144 int trackingDestinationLineEnd() const; setTrackingDestinationLineNumber(int i)145 void setTrackingDestinationLineNumber(int i) { m_trackingDestinationLineNo = i; } 146 sourceLineAt(int i)147 DifferenceString* sourceLineAt(int i) const { return m_sourceLines[i]; } destinationLineAt(int i)148 DifferenceString* destinationLineAt(int i) const { return m_destinationLines[i]; } 149 sourceLines()150 const DifferenceStringList sourceLines() const { return m_sourceLines; } destinationLines()151 const DifferenceStringList destinationLines() const { return m_destinationLines; } 152 hasConflict()153 bool hasConflict() const 154 { 155 return m_conflicts; 156 } setConflict(bool conflicts)157 void setConflict(bool conflicts) 158 { 159 m_conflicts = conflicts; 160 } 161 isUnsaved()162 bool isUnsaved() const 163 { 164 return m_unsaved; 165 } setUnsaved(bool unsaved)166 void setUnsaved(bool unsaved) 167 { 168 m_unsaved = unsaved; 169 } 170 171 void apply(bool apply); 172 /// Apply without emitting any signals 173 void applyQuietly(bool apply); applied()174 bool applied() const { return m_applied; } 175 setType(int type)176 void setType(int type) { m_type = type; } 177 178 void addSourceLine(QString line); 179 void addDestinationLine(QString line); 180 181 /** This method will calculate the differences between the individual strings and store them as Markers */ 182 void determineInlineDifferences(); 183 184 QString recreateDifference() const; 185 186 Q_SIGNALS: 187 void differenceApplied(Difference*); 188 189 private: 190 int m_type; 191 192 int m_sourceLineNo; 193 int m_destinationLineNo; 194 int m_trackingDestinationLineNo; 195 196 DifferenceStringList m_sourceLines; 197 DifferenceStringList m_destinationLines; 198 199 bool m_applied; 200 bool m_conflicts; 201 bool m_unsaved; 202 }; 203 204 using DifferenceList = QList<Difference*>; 205 using DifferenceListIterator = QList<Difference*>::iterator; 206 using DifferenceListConstIterator = QList<Difference*>::const_iterator; 207 208 } // End of namespace Diff2 209 210 #endif 211 212