Mercurial > hg > easyhg
comparison grapher.cpp @ 268:b8ded5213d16
* Revert the grapher change from revision ec2baee80833 on Dec 19th 2010. The change definitely performed worse than the original (now reinstated) logic in the real-world soundsoftware-site case, with far more connection overlaps and ambiguous placements.
author | Chris Cannam |
---|---|
date | Mon, 17 Jan 2011 11:44:17 +0000 |
parents | be483734bde5 |
children | cc95394e2392 |
comparison
equal
deleted
inserted
replaced
267:45f69889d28d | 268:b8ded5213d16 |
---|---|
21 #include "debug.h" | 21 #include "debug.h" |
22 #include "changesetscene.h" | 22 #include "changesetscene.h" |
23 | 23 |
24 #include <iostream> | 24 #include <iostream> |
25 | 25 |
26 #include <QMultiMap> | 26 int Grapher::findAvailableColumn(int row, int parent, bool preferParentCol) |
27 | |
28 int Grapher::findAvailableColumn(int row, int parent, int sign, | |
29 bool preferParentCol) | |
30 { | 27 { |
31 int col = parent; | 28 int col = parent; |
32 if (preferParentCol) { | 29 if (preferParentCol) { |
33 if (isAvailable(row, col)) return col; | 30 if (isAvailable(row, col)) return col; |
34 } | 31 } |
37 } | 34 } |
38 while (col < 0) { | 35 while (col < 0) { |
39 if (isAvailable(row, ++col)) return col; | 36 if (isAvailable(row, ++col)) return col; |
40 } | 37 } |
41 col = parent; | 38 col = parent; |
42 if (sign == 0) { | 39 int sign = (col < 0 ? -1 : 1); |
43 sign = (col < 0 ? -1 : 1); | |
44 } | |
45 while (1) { | 40 while (1) { |
46 col += sign; | 41 col += sign; |
47 if (isAvailable(row, col)) return col; | 42 if (isAvailable(row, col)) return col; |
48 } | 43 } |
49 } | 44 } |
145 ChangesetItem *item = m_items[id]; | 140 ChangesetItem *item = m_items[id]; |
146 | 141 |
147 int col = 0; | 142 int col = 0; |
148 int row = item->row(); | 143 int row = item->row(); |
149 QString branch = cs->branch(); | 144 QString branch = cs->branch(); |
150 int branchHome = m_branchHomes[branch]; | |
151 | 145 |
152 int nparents = cs->parents().size(); | 146 int nparents = cs->parents().size(); |
153 QString parentId; | 147 QString parentId; |
154 int parentsOnSameBranch = 0; | 148 int parentsOnSameBranch = 0; |
155 | 149 |
156 switch (nparents) { | 150 switch (nparents) { |
157 | 151 |
158 case 0: | 152 case 0: |
159 col = findAvailableColumn(row, branchHome, 0, true); | 153 col = m_branchHomes[cs->branch()]; |
154 col = findAvailableColumn(row, col, true); | |
160 break; | 155 break; |
161 | 156 |
162 case 1: | 157 case 1: |
163 parentId = cs->parents()[0]; | 158 parentId = cs->parents()[0]; |
164 | 159 |
168 col = m_branchHomes[branch]; | 163 col = m_branchHomes[branch]; |
169 } else { | 164 } else { |
170 col = m_items[parentId]->column(); | 165 col = m_items[parentId]->column(); |
171 } | 166 } |
172 | 167 |
173 col = findAvailableColumn(row, col, branchHome - col, true); | 168 col = findAvailableColumn(row, col, true); |
174 break; | 169 break; |
175 | 170 |
176 case 2: | 171 case 2: |
177 // a merge: behave differently if parents are both on the same | 172 // a merge: behave differently if parents are both on the same |
178 // branch (we also want to behave differently for nodes that | 173 // branch (we also want to behave differently for nodes that |
188 } | 183 } |
189 } | 184 } |
190 | 185 |
191 if (parentsOnSameBranch > 0) { | 186 if (parentsOnSameBranch > 0) { |
192 col /= parentsOnSameBranch; | 187 col /= parentsOnSameBranch; |
193 col = findAvailableColumn(item->row(), col, 0, true); | 188 col = findAvailableColumn(item->row(), col, true); |
194 } else { | 189 } else { |
195 col = findAvailableColumn(item->row(), col, 0, false); | 190 col = findAvailableColumn(item->row(), col, false); |
196 } | 191 } |
197 break; | 192 break; |
198 } | 193 } |
199 | 194 |
200 DEBUG << "putting " << cs->id().toStdString() << " at col " << col << endl; | 195 DEBUG << "putting " << cs->id().toStdString() << " at col " << col << endl; |
207 // given the same column as us (we already noted that its | 202 // given the same column as us (we already noted that its |
208 // connecting line would end at our row) | 203 // connecting line would end at our row) |
209 | 204 |
210 if (m_uncommittedParents.contains(id)) { | 205 if (m_uncommittedParents.contains(id)) { |
211 if (m_uncommittedParents[0] == id) { | 206 if (m_uncommittedParents[0] == id) { |
212 int ucol = findAvailableColumn(row-1, col, branchHome - col, true); | 207 int ucol = findAvailableColumn(row-1, col, true); |
213 m_uncommitted->setColumn(ucol); | 208 m_uncommitted->setColumn(ucol); |
214 m_haveAllocatedUncommittedColumn = true; | 209 m_haveAllocatedUncommittedColumn = true; |
215 } | 210 } |
216 // also, if the uncommitted item has a different branch from | 211 // also, if the uncommitted item has a different branch from |
217 // any of its parents, tell it to show the branch | 212 // any of its parents, tell it to show the branch |
261 if (special.size() == 2) { | 256 if (special.size() == 2) { |
262 DEBUG << "handling split-in-two for children " << special[0] << " and " << special[1] << endl; | 257 DEBUG << "handling split-in-two for children " << special[0] << " and " << special[1] << endl; |
263 for (int i = 0; i < 2; ++i) { | 258 for (int i = 0; i < 2; ++i) { |
264 int off = i * 2 - 1; // 0 -> -1, 1 -> 1 | 259 int off = i * 2 - 1; // 0 -> -1, 1 -> 1 |
265 ChangesetItem *it = m_items[special[i]]; | 260 ChangesetItem *it = m_items[special[i]]; |
266 it->setColumn(findAvailableColumn(it->row(), col + off, 0, true)); | 261 it->setColumn(findAvailableColumn(it->row(), col + off, true)); |
267 for (int r = row-1; r >= it->row(); --r) { | 262 for (int r = row-1; r >= it->row(); --r) { |
268 m_alloc[r].insert(it->column()); | 263 m_alloc[r].insert(it->column()); |
269 } | 264 } |
270 m_handled.insert(special[i]); | 265 m_handled.insert(special[i]); |
271 } | 266 } |
285 return true; | 280 return true; |
286 } | 281 } |
287 | 282 |
288 void Grapher::allocateBranchHomes(Changesets csets) | 283 void Grapher::allocateBranchHomes(Changesets csets) |
289 { | 284 { |
290 QMap<QString, int> branchCounts; | 285 foreach (Changeset *cs, csets) { |
291 QMap<QString, QString> branchParents; | |
292 | |
293 QStringList branches; | |
294 | |
295 foreach (Changeset *cs, csets) { | |
296 | |
297 QString branch = cs->branch(); | 286 QString branch = cs->branch(); |
298 | |
299 if (!branchCounts.contains(branch)) { | |
300 // Guess at the parent branch for this one which we | |
301 // haven't seen before. This is not entirely reliable, but | |
302 // it doesn't need to be | |
303 if (!cs->parents().empty()) { | |
304 QString firstParentId = cs->parents()[0]; | |
305 if (m_changesets.contains(firstParentId)) { | |
306 Changeset *firstParent = m_changesets[firstParentId]; | |
307 branchParents[branch] = firstParent->branch(); | |
308 } | |
309 } | |
310 branches.push_back(branch); | |
311 } | |
312 | |
313 branchCounts[branch]++; | |
314 | |
315 ChangesetItem *item = m_items[cs->id()]; | 287 ChangesetItem *item = m_items[cs->id()]; |
316 if (!item) continue; | 288 if (!item) continue; |
317 | |
318 int row = item->row(); | 289 int row = item->row(); |
319 if (!m_branchRanges.contains(branch)) { | 290 if (!m_branchRanges.contains(branch)) { |
320 m_branchRanges[branch] = Range(row, row); | 291 m_branchRanges[branch] = Range(row, row); |
321 } else { | 292 } else { |
322 Range p = m_branchRanges[branch]; | 293 Range p = m_branchRanges[branch]; |
326 } | 297 } |
327 } | 298 } |
328 | 299 |
329 m_branchHomes[""] = 0; | 300 m_branchHomes[""] = 0; |
330 m_branchHomes["default"] = 0; | 301 m_branchHomes["default"] = 0; |
331 /* | 302 |
332 QStringList orderedBranches; // will be ordered by "popularity" | 303 foreach (QString branch, m_branchRanges.keys()) { |
333 | |
334 QMultiMap<int, QString> branchesByCount; | |
335 foreach (QString branch, branchCounts.keys()) { | |
336 branchesByCount.insert(branchCounts[branch], branch); | |
337 } | |
338 foreach (QString branch, branchesByCount) { | |
339 orderedBranches.push_front(branch); | |
340 } | |
341 */ | |
342 int sign = -1; | |
343 | |
344 foreach (QString branch, branches) { | |
345 if (branch == "") continue; | 304 if (branch == "") continue; |
346 QSet<int> taken; | 305 QSet<int> taken; |
347 taken.insert(0); | 306 taken.insert(0); |
348 Range myRange = m_branchRanges[branch]; | 307 Range myRange = m_branchRanges[branch]; |
349 foreach (QString other, m_branchRanges.keys()) { | 308 foreach (QString other, m_branchRanges.keys()) { |
354 taken.insert(m_branchHomes[other]); | 313 taken.insert(m_branchHomes[other]); |
355 } | 314 } |
356 } | 315 } |
357 } | 316 } |
358 int home = 2; | 317 int home = 2; |
359 QString parent = branchParents[branch]; | |
360 if (parent != "" && parent != "default" && | |
361 m_branchHomes.contains(parent)) { | |
362 home = m_branchHomes[parent]; | |
363 if (home > 0) sign = 1; | |
364 else sign = -1; | |
365 } else { | |
366 sign = -sign; | |
367 } | |
368 while (taken.contains(home)) { | 318 while (taken.contains(home)) { |
369 home = home + 2 * sign; | 319 if (home > 0) { |
320 if (home % 2 == 1) { | |
321 home = -home; | |
322 } else { | |
323 home = home + 1; | |
324 } | |
325 } else { | |
326 if ((-home) % 2 == 1) { | |
327 home = home + 1; | |
328 } else { | |
329 home = -(home-2); | |
330 } | |
331 } | |
370 } | 332 } |
371 m_branchHomes[branch] = home; | 333 m_branchHomes[branch] = home; |
372 } | 334 } |
373 | 335 |
374 foreach (QString branch, branches) { | 336 foreach (QString branch, m_branchRanges.keys()) { |
375 DEBUG << branch << ": pop " << branchCounts[branch] << ", parent " << branchParents[branch] << ", range " << m_branchRanges[branch].first << " - " << m_branchRanges[branch].second << ", home " << m_branchHomes[branch] << endl; | 337 DEBUG << branch.toStdString() << ": " << m_branchRanges[branch].first << " - " << m_branchRanges[branch].second << ", home " << m_branchHomes[branch] << endl; |
376 } | 338 } |
377 } | 339 } |
378 | 340 |
379 static bool | 341 static bool |
380 compareChangesetsByDate(Changeset *const &a, Changeset *const &b) | 342 compareChangesetsByDate(Changeset *const &a, Changeset *const &b) |