d9a508ba133bec6dd7435bf9608a81ac95a07c16
[profile/ivi/qtdeclarative.git] / src / declarative / util / qdeclarativechangeset.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativechangeset_p.h"
43
44 void QDeclarativeChangeSet::insertInsert(int start, int end)
45 {
46     const int count = end - start;
47
48     // Moved signals.
49     QVector<Move>::iterator move = m_moves.begin();
50     for (; move != m_moves.end() && start >= move->maximum(); ++move) {}
51     for (; move != m_moves.end() && end >= move->minimum(); ++move) {
52         if (start <= move->tstart) {
53             move->tstart += count;
54             move->tend += count;
55         } else if (start < move->tend) {
56             int relativeStart = start - move->tstart;
57
58             move = m_moves.insert(move, Move(
59                     move->fstart + count, move->fstart + count + relativeStart, move->tstart));
60             ++move;
61             move->fstart += relativeStart;
62             move->tstart += count + relativeStart;
63             move->tend += count;
64
65             start -= relativeStart;
66             end -= relativeStart;
67         } else {
68             start -= move->count();
69             end -= move->count();
70         }
71
72         if (start <= move->fstart) {
73             move->fstart += count;
74             move->fend += count;
75         } else if (start < move->tstart) {
76             start += move->count();
77             end += move->count();
78         }
79
80     }
81     for (; move != m_moves.end(); ++move) {
82         move->fstart += count;
83         move->fend += count;
84         move->tstart += count;
85         move->tend += count;
86     }
87
88     // Inserted signals.
89     QVector<Insert>::iterator insert = m_inserts.begin();
90     for (; insert != m_inserts.end(); ++insert) {
91         if (start < insert->start) {
92             insert = m_inserts.insert(insert, Insert(start, end));
93             break;
94         } else if (start <= insert->end) {
95             insert->end += count;
96             break;
97         }
98     }
99     if (insert == m_inserts.end()) {
100         m_inserts.append(Insert(start, end));
101     } else for (++insert; insert != m_inserts.end(); ++insert) {
102         insert->start += count;
103         insert->end += count;
104     }
105
106
107     // Changed signals.
108     QVector<Change>::iterator change = m_changes.begin();
109     for (; change != m_changes.end() && start != change->start && start < change->end; ++change) {
110         if (start > change->start) {
111             int relativeStart = start - change->start;
112             change = m_changes.insert(change, Change(change->start, change->start + relativeStart));
113             ++change;
114             change->start += count + relativeStart;
115             change->end += count - relativeStart;
116             break;
117         }
118     }
119     for (; change != m_changes.end(); ++change) {
120         change->start += count;
121         change->end += count;
122     }
123 }
124
125 void QDeclarativeChangeSet::insertRemove(int start, int end)
126 {
127     // Changed Signals.
128     QVector<Change>::iterator change = m_changes.begin();
129     for (; change != m_changes.end() && start >= change->end; ++change) {}
130     for (; change != m_changes.end() && end < change->start; ++change) {
131         const int removeCount = qMin(change->end, end) - qMax(change->start, start);
132         change->end -= removeCount;
133         if (change->start == change->end) {
134             change = m_changes.erase(change);
135         } else if (start < change->start) {
136             change->start = start;
137         }
138     }
139     const int count = end - start;
140     for (; change != m_changes.end(); ++change) {
141         change->start -= count;
142         change->end -= count;
143     }
144
145     QVector<Remove> removeChanges;
146
147     // Moved signals.
148     QVector<Move>::iterator move = m_moves.begin();
149     for (; move != m_moves.end() && start >= move->maximum(); ++move) {}
150     for (; move != m_moves.end() && end >= move->minimum(); ++move) {
151         if (move->fstart < move->tstart) {
152             if (start < move->fstart) {
153                 const int difference = move->fstart - start;
154                 move->fend -= difference;
155                 move->fstart = start;
156                 move->tstart -= difference;
157                 move->tend -= difference;
158
159                 removeChanges.append(Remove(start, start + difference));
160                 end -= difference;
161             }
162             if (end < move->tstart) {
163                 move->tstart -= end - start;
164                 move->tend -= end - start;
165             } else if (start < move->tend) {
166                 const int difference = qMin(move->tend, end) - move->tstart;
167                 removeChanges.append(Remove(
168                         move->fstart , move->fstart + difference));
169                 end -= difference;
170
171                 move->fend -= difference;
172                 move->tstart -= end - start;
173                 move->tend -=  end - start + difference;
174             }
175             start += move->count();
176             end += move->count();
177         } else {
178             if (start < move->tend) {
179                 const int offset = qMax(0, start - move->tstart);
180                 const int difference = qMin(move->tend, end) - qMax(move->tstart, start);
181
182                 removeChanges.append(Remove(
183                         move->fstart + offset, move->fstart + offset + difference));
184                 start -= offset;
185                 end -= offset + difference;
186
187                 move->fend -= difference;
188                 move->tstart = start;
189                 move->tend = start + move->fend - move->fstart;
190             } else {
191                 start -= move->count();
192                 end -= move->count();
193             }
194
195             move->fstart -= end - start;
196             move->fend -= end - start;
197
198             if (start > move->fstart) {
199                 const int offset = start - move->fstart;
200                 const int difference = qMin(move->fend, end) - start;
201                 removeChanges.append(Remove(
202                         move->fstart + end - start + offset + difference ,
203                         move->fend + end - start + offset));
204                 end -= offset;
205                 move->fstart += offset;
206                 move->fend += offset;
207             }
208         }
209
210         if (move->tstart == move->tend || move->fstart == move->tstart) {
211             move = m_moves.erase(move);
212             --move;
213         }
214     }
215     for (; move != m_moves.end(); ++move) {
216         move->fstart -= count;
217         move->fend -= count;
218         move->tstart -= count;
219         move->tend -= count;
220     }
221
222     if (start != end)
223         removeChanges.append(Remove(start, end));
224
225     foreach (const Remove &r, removeChanges) {
226         int start = r.start;
227         int end = r.end;
228
229         QVector<Insert>::iterator insert = m_inserts.end() - 1;
230         for (const int count = end - start; insert != m_inserts.begin() - 1 && insert->start >= end; --insert) {
231                 insert->start -= count;
232                 insert->end -= count;
233         }
234         for (; insert != m_inserts.begin() - 1 && insert->end > start; --insert) {
235             const int removeCount = qMin(insert->end, end) - qMax(insert->start, start);
236             insert->end -= removeCount;
237             if (insert->start == insert->end) {
238                 insert = m_inserts.erase(insert);
239             } else if (start < insert->start) {
240                 insert->end -= insert->start - start;
241                 insert->start = start;
242             } else {
243                 start -= insert->count();
244                 end -= insert->count();
245             }
246             end -= removeCount;
247             if (start == end)
248                  return;
249          }
250         // Adjust the index to compensate for any inserts prior to the remove position..
251         for (; insert != m_inserts.begin() - 1; --insert) {
252             start -= insert->count();
253             end -= insert->count();
254         }
255
256         // Removed signals.
257         QVector<Remove>::iterator remove = m_removes.begin();
258         for (; remove != m_removes.end(); ++remove) {
259             if (end < remove->start) {
260                 remove = m_removes.insert(remove, Remove(start, end));
261                 break;
262             } else if (start <= remove->start) {
263                 remove->end += end - remove->start;
264                 remove->start = start;
265
266                 QVector<Remove>::iterator rbegin = remove;
267                 QVector<Remove>::iterator rend = ++rbegin;
268                 for (; rend != m_removes.end() && rend->start <= remove->end; ++rend)
269                     remove->end += rend->count();
270                 if (rbegin != rend) {
271                     remove = m_removes.erase(rbegin, rend);
272                 }
273                 break;
274             }
275         }
276         if (remove != m_removes.end()) {
277             const int count = end - start;
278             for (++remove; remove != m_removes.end(); ++remove) {
279                 remove->start -= count;
280                 remove->end -= count;
281             }
282         } else {
283             m_removes.append(Remove(start, end));
284         }
285     }
286 }
287
288 void QDeclarativeChangeSet::insertMove(int start, int end, int to)
289 {
290     QVector<Insert> insertChanges;
291     QVector<Move> moveChanges;
292
293     int fStart = start;
294     int fTo = to;
295     int fEnd = end;
296     int &bStart = fTo;
297     int bEnd = to + end - start;
298
299     if (start > to) {
300         qSwap(fStart, bStart);
301         qSwap(fEnd, bEnd);
302     }
303
304     // Inserted signals.
305     QVector<Insert>::iterator insert = m_inserts.begin();
306     if (start < to) {
307         for (; insert != m_inserts.end() && fStart >= insert->end; ++insert) {}
308         for (; insert != m_inserts.end() && fEnd > insert->start; ++insert) {
309             const int removeCount = qMin(insert->end, fEnd) - qMax(insert->start, fStart);
310             const int relativeStart = fStart - insert->start;
311             const int relativeEnd = qMax(0, fEnd - insert->end);
312
313             insert->end -= removeCount;
314             if (insert->start == insert->end) {
315                 insert = m_inserts.erase(insert);
316                 --insert;
317             }
318
319             if (relativeStart < 0) {
320                 moveChanges.append(Move(fStart, fStart - relativeStart, fTo + relativeEnd));
321                 fTo -= relativeStart;
322             }
323
324             fTo += removeCount;
325             insertChanges.append(Insert(bEnd - removeCount, bEnd));
326         }
327     } else {
328         for (; insert != m_inserts.end() && bStart >= insert->end; ++insert) {}
329         for (; insert != m_inserts.end() && bEnd > insert->start; ++insert) {
330             const int removeCount = qMin(insert->end, bEnd) - qMax(insert->start, bStart);
331             const int relativeStart = bStart - insert->start;
332
333             insert->start += removeCount;
334             if (insert->start == insert->end) {
335                 insert->start = fStart;
336                 insert->end = insert->start + removeCount;
337             } else {
338                 insert = m_inserts.insert(insert, Insert(fStart, fStart + removeCount));
339                 ++insert;
340             }
341             if (relativeStart < 0) {
342                 moveChanges.append(Move(fStart, fStart - relativeStart, fTo + removeCount));
343                 fStart -= relativeStart;
344                 fTo -= relativeStart;
345             }
346             fStart += removeCount;
347             fTo += removeCount;
348         }
349     }
350
351     if (fTo != bEnd)
352         moveChanges.append(Move(fStart, fStart + bEnd - fTo, fTo));
353
354     QVector<Insert>::iterator it = insertChanges.begin();
355     for (insert = m_inserts.begin(); it != insertChanges.end() && insert != m_inserts.end();++insert) {
356         if (it->start < insert->start) {
357             insert = m_inserts.insert(insert, *it);
358             ++it;
359         } else if (it->start <= insert->end) {
360             insert->end += it->count();
361             ++it;
362         }
363     }
364     for (; it != insertChanges.end(); ++it)
365         m_inserts.append(*it);
366
367     // Insert queued moved signals ordered by destination position.
368     QVector<Move>::iterator move = m_moves.begin();
369     if (start > to) {
370         for (QVector<Move>::iterator it = moveChanges.begin(); it != moveChanges.end(); ++it) {
371             it->fend += it->tstart - it->fstart;
372             it->tend -=it->tstart - it->fstart;
373             qSwap(it->fstart, it->tstart);
374             for (; move != m_moves.end() && it->to >= qMin(move->fstart, move->tstart); ++move) {}
375             move = m_moves.insert(move, *it);
376         }
377     } else {
378         for (QVector<Move>::iterator it = moveChanges.begin(); it != moveChanges.end(); ++it) {
379             for (; move != m_moves.end() && it->start >= qMin(move->fstart, move->tstart); ++move) {}
380             move = m_moves.insert(move, *it);
381         }
382     }
383 }
384
385 void QDeclarativeChangeSet::insertChange(int start, int end)
386 {
387     QVector<Change> filteredChanges;
388
389     // Inserted signals (don't emit change signals on new items).
390     QVector<Insert>::iterator insert = m_inserts.begin();
391     for (; insert != m_inserts.end() && start >= insert->end; ++insert) {}
392     for (; insert != m_inserts.end() && end > insert->start; ++insert) {
393         if (start < insert->start)
394             filteredChanges.append(Change(start, insert->start));
395         start = insert->end;
396     }
397     if (start < end)
398         filteredChanges.append(Change(start, end));
399
400     // Find the union of the existing and filtered sets of change signals.
401     QVector<Change>::iterator change = m_changes.begin();
402     for (QVector<Change>::iterator it = filteredChanges.begin(); it != filteredChanges.end(); ++it) {
403         for (; change != m_changes.end() && change->end < it->start; ++change) {}
404         if (change == m_changes.end() || change->start > it->end) {
405             change = m_changes.insert(change, *it);
406         } else {
407             if (it->start < change->start)
408                 change->start = it->start;
409
410             if (it->end > change->end) {
411                 change->end = it->end;
412                 QVector<Change>::iterator rbegin = change;
413                 QVector<Change>::iterator rend = ++rbegin;
414                 for (; rend != m_changes.end() && rend->start <= change->end; ++rend) {
415                     if (rend->end > change->end)
416                         change->end = rend->end;
417                 }
418                 if (rbegin != rend) {
419                     change = m_changes.erase(rbegin, rend);
420                     --change;
421                 }
422             }
423         }
424     }
425
426 }
427
428 QDebug operator <<(QDebug debug, const QDeclarativeChangeSet &set)
429 {
430     foreach (const QDeclarativeChangeSet::Remove &remove, set.removes())
431         debug.nospace() << "QDeclarativeChangeSet::Remove(" << remove.start << "," << remove.end << ")";
432     foreach (const QDeclarativeChangeSet::Insert &insert, set.inserts())
433         debug.nospace() << "QDeclarativeChangeSet::Insert(" << insert.start << "," << insert.end << ")";
434     foreach (const QDeclarativeChangeSet::Move &move, set.moves())
435         debug.nospace() << "QDeclarativeChangeSet::Move(" << move.start << "," << move.end << "," << move.to << ")";
436     foreach (const QDeclarativeChangeSet::Change &change, set.changes())
437         debug.nospace() << "QDeclarativeChangeSet::Change(" << change.start << "," << change.end << ")";
438     return debug;
439 }
440