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