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)