diff grapher.cpp @ 106:729438d70af8

* Retrieve and store current branch and heads; some refactoring
author Chris Cannam
date Thu, 25 Nov 2010 17:54:35 +0000
parents 10eb97683aa9
children 4bd17f36d059
line wrap: on
line diff
--- a/grapher.cpp	Thu Nov 25 17:21:32 2010 +0000
+++ b/grapher.cpp	Thu Nov 25 17:54:35 2010 +0000
@@ -23,40 +23,38 @@
 
 #include <iostream>
 
-int
-Grapher::findAvailableColumn(int row, int parent, bool preferParentCol)
+int Grapher::findAvailableColumn(int row, int parent, bool preferParentCol)
 {
     int col = parent;
     if (preferParentCol) {
-	if (!m_alloc[row].contains(col)) {
-	    return col;
-	}
+        if (!m_alloc[row].contains(col)) {
+            return col;
+        }
     }
     while (col > 0) {
-	if (!m_alloc[row].contains(--col)) return col;
+        if (!m_alloc[row].contains(--col)) return col;
     }
     while (col < 0) {
-	if (!m_alloc[row].contains(++col)) return col;
+        if (!m_alloc[row].contains(++col)) return col;
     }
     col = parent;
     int sign = (col < 0 ? -1 : 1);
     while (1) {
-	col += sign;
-	if (!m_alloc[row].contains(col)) return col;
+        col += sign;
+        if (!m_alloc[row].contains(col)) return col;
     }
 }
 
-void
-Grapher::layoutRow(QString id)
+void Grapher::layoutRow(QString id)
 {
     if (m_handled.contains(id)) {
-	return;
+        return;
     }
     if (!m_changesets.contains(id)) {
-	throw LayoutException(QString("Changeset %1 not in ID map").arg(id));
+        throw LayoutException(QString("Changeset %1 not in ID map").arg(id));
     }
     if (!m_items.contains(id)) {
-	throw LayoutException(QString("Changeset %1 not in item map").arg(id));
+        throw LayoutException(QString("Changeset %1 not in item map").arg(id));
     }
     Changeset *cs = m_changesets[id];
     ChangesetItem *item = m_items[id];
@@ -66,23 +64,23 @@
     int nparents = cs->parents().size();
 
     if (nparents > 0) {
-	bool haveRow = false;
-	foreach (QString parentId, cs->parents()) {
+        bool haveRow = false;
+        foreach (QString parentId, cs->parents()) {
 
-	    if (!m_changesets.contains(parentId)) continue;
-	    if (!m_items.contains(parentId)) continue;
+            if (!m_changesets.contains(parentId)) continue;
+            if (!m_items.contains(parentId)) continue;
 
-	    if (!m_handled.contains(parentId)) {
-		layoutRow(parentId);
-	    }
+            if (!m_handled.contains(parentId)) {
+                layoutRow(parentId);
+            }
 
-	    ChangesetItem *parentItem = m_items[parentId];
-	    if (!haveRow || parentItem->row() < row) {
-		row = parentItem->row();
-		haveRow = true;
-	    }
-	}
-	row = row - 1;
+            ChangesetItem *parentItem = m_items[parentId];
+            if (!haveRow || parentItem->row() < row) {
+                row = parentItem->row();
+                haveRow = true;
+            }
+        }
+        row = row - 1;
     }
 
     // row is now an upper bound on our eventual row (because we want
@@ -92,7 +90,7 @@
 
     QString date = cs->age();
     while (m_rowDates.contains(row) && m_rowDates[row] != date) {
-	--row;
+        --row;
     }
 
     // We have already laid out all nodes that have earlier timestamps
@@ -101,28 +99,27 @@
     // the map yet (it cannot have an earlier date)
 
     if (!m_rowDates.contains(row)) {
-	m_rowDates[row] = date;
+        m_rowDates[row] = date;
     }
 
     std::cerr << "putting " << cs->id().toStdString() << " at row " << row 
-	      << std::endl;
+            << std::endl;
 
     item->setRow(row);
     m_handled.insert(id);
 }
 
-void
-Grapher::layoutCol(QString id)
+void Grapher::layoutCol(QString id)
 {
     if (m_handled.contains(id)) {
-	std::cerr << "Already looked at " << id.toStdString() << std::endl;
-	return;
+        std::cerr << "Already looked at " << id.toStdString() << std::endl;
+        return;
     }
     if (!m_changesets.contains(id)) {
-	throw LayoutException(QString("Changeset %1 not in ID map").arg(id));
+        throw LayoutException(QString("Changeset %1 not in ID map").arg(id));
     }
     if (!m_items.contains(id)) {
-	throw LayoutException(QString("Changeset %1 not in item map").arg(id));
+        throw LayoutException(QString("Changeset %1 not in item map").arg(id));
     }
 
     Changeset *cs = m_changesets[id];
@@ -141,46 +138,46 @@
     switch (nparents) {
 
     case 0:
-	col = m_branchHomes[cs->branch()];
-	col = findAvailableColumn(row, col, true);
-	break;
+        col = m_branchHomes[cs->branch()];
+        col = findAvailableColumn(row, col, true);
+        break;
 
     case 1:
-	parentId = cs->parents()[0];
+        parentId = cs->parents()[0];
 
-	if (!m_changesets.contains(parentId) ||
-	    m_changesets[parentId]->branch() != branch) {
-	    // new branch
-	    col = m_branchHomes[branch];
-	} else {
-	    col = m_items[parentId]->column();
-	}
+        if (!m_changesets.contains(parentId) ||
+            m_changesets[parentId]->branch() != branch) {
+            // new branch
+            col = m_branchHomes[branch];
+        } else {
+            col = m_items[parentId]->column();
+        }
 
-	col = findAvailableColumn(row, col, true);
-	break;
+        col = findAvailableColumn(row, col, true);
+        break;
 
     case 2:
-	// a merge: behave differently if parents are both on the same
-	// branch (we also want to behave differently for nodes that
-	// have multiple children on the same branch -- spreading them
-	// out rather than having affinity to a specific branch)
+        // a merge: behave differently if parents are both on the same
+        // branch (we also want to behave differently for nodes that
+        // have multiple children on the same branch -- spreading them
+        // out rather than having affinity to a specific branch)
 
-	foreach (QString parentId, cs->parents()) {
-	    if (!m_changesets.contains(parentId)) continue;
-	    if (m_changesets[parentId]->branch() == branch) {
-		ChangesetItem *parentItem = m_items[parentId];
-		col += parentItem->column();
-		parentsOnSameBranch++;
-	    }
-	}
+        foreach (QString parentId, cs->parents()) {
+            if (!m_changesets.contains(parentId)) continue;
+            if (m_changesets[parentId]->branch() == branch) {
+                ChangesetItem *parentItem = m_items[parentId];
+                col += parentItem->column();
+                parentsOnSameBranch++;
+            }
+        }
 
-	if (parentsOnSameBranch > 0) {
-	    col /= parentsOnSameBranch;
-	    col = findAvailableColumn(item->row(), col, true);
-	} else {
-	    col = findAvailableColumn(item->row(), col, false);
-	}
-	break;
+        if (parentsOnSameBranch > 0) {
+            col /= parentsOnSameBranch;
+            col = findAvailableColumn(item->row(), col, true);
+        } else {
+            col = findAvailableColumn(item->row(), col, false);
+        }
+        break;
     }
 
     std::cerr << "putting " << cs->id().toStdString() << " at col " << col << std::endl;
@@ -201,13 +198,13 @@
     foreach (QString childId, cs->children()) {
         if (!m_changesets.contains(childId)) continue;
         Changeset *child = m_changesets[childId];
-	int childRow = m_items[childId]->row();
+        int childRow = m_items[childId]->row();
         if (child->parents().size() > 1 ||
-	    child->branch() == cs->branch()) {
+            child->branch() == cs->branch()) {
             for (int r = row-1; r > childRow; --r) {
                 m_alloc[r].insert(col);
             }
-	}	    
+        }
     }
 
     // look for the case where exactly two children have the same
@@ -215,31 +212,30 @@
 
     if (nchildren > 1) {
 
-	QList<QString> special;
-	foreach (QString childId, cs->children()) {
-	    if (!m_changesets.contains(childId)) continue;
-	    Changeset *child = m_changesets[childId];
-	    if (child->branch() == branch &&
-		child->parents().size() == 1) {
-		special.push_back(childId);
-	    }
-	}
-	if (special.size() == 2) {
-	    for (int i = 0; i < 2; ++i) {
-		int off = i * 2 - 1; // 0 -> -1, 1 -> 1
-		ChangesetItem *it = m_items[special[i]];
-		it->setColumn(findAvailableColumn(it->row(), col + off, true));
-		for (int r = row-1; r >= it->row(); --r) {
-		    m_alloc[r].insert(it->column());
-		}
-		m_handled.insert(special[i]);
-	    }
-	}
+        QList<QString> special;
+        foreach (QString childId, cs->children()) {
+            if (!m_changesets.contains(childId)) continue;
+            Changeset *child = m_changesets[childId];
+            if (child->branch() == branch &&
+                child->parents().size() == 1) {
+                special.push_back(childId);
+            }
+        }
+        if (special.size() == 2) {
+            for (int i = 0; i < 2; ++i) {
+                int off = i * 2 - 1; // 0 -> -1, 1 -> 1
+                ChangesetItem *it = m_items[special[i]];
+                it->setColumn(findAvailableColumn(it->row(), col + off, true));
+                for (int r = row-1; r >= it->row(); --r) {
+                    m_alloc[r].insert(it->column());
+                }
+                m_handled.insert(special[i]);
+            }
+        }
     }
 }
 
-bool
-Grapher::rangesConflict(const Range &r1, const Range &r2)
+bool Grapher::rangesConflict(const Range &r1, const Range &r2)
 {
     // allow some additional space at edges.  we really ought also to
     // permit space at the end of a branch up to the point where the
@@ -251,79 +247,77 @@
     return true;
 }
 
-void
-Grapher::allocateBranchHomes(Changesets csets)
+void Grapher::allocateBranchHomes(Changesets csets)
 {
     foreach (Changeset *cs, csets) {
-	QString branch = cs->branch();
-	ChangesetItem *item = m_items[cs->id()];
-	if (!item) continue;
-	int row = item->row();
-	if (!m_branchRanges.contains(branch)) {
-	    m_branchRanges[branch] = Range(row, row);
-	} else {
-	    Range p = m_branchRanges[branch];
-	    if (row < p.first) p.first = row;
-	    if (row > p.second) p.second = row;
-	    m_branchRanges[branch] = p;
-	}
+        QString branch = cs->branch();
+        ChangesetItem *item = m_items[cs->id()];
+        if (!item) continue;
+        int row = item->row();
+        if (!m_branchRanges.contains(branch)) {
+            m_branchRanges[branch] = Range(row, row);
+        } else {
+            Range p = m_branchRanges[branch];
+            if (row < p.first) p.first = row;
+            if (row > p.second) p.second = row;
+            m_branchRanges[branch] = p;
+        }
     }
 
     m_branchHomes[""] = 0;
 
     foreach (QString branch, m_branchRanges.keys()) {
-	if (branch == "") continue;
-	QSet<int> taken;
-	taken.insert(0);
-	Range myRange = m_branchRanges[branch];
-	foreach (QString other, m_branchRanges.keys()) {
-	    if (other == branch || other == "") continue;
-	    Range otherRange = m_branchRanges[other];
-	    if (rangesConflict(myRange, otherRange)) {
-		if (m_branchHomes.contains(other)) {
-		    taken.insert(m_branchHomes[other]);
-		}
-	    }
-	}
-	int home = 2;
-	while (taken.contains(home)) {
-	    if (home > 0) {
-		if (home % 2 == 1) {
-		    home = -home;
-		} else {
-		    home = home + 1;
-		}
-	    } else {
-		if ((-home) % 2 == 1) {
-		    home = home + 1;
-		} else {
-		    home = -(home-2);
-		}
-	    }
-	}
-	m_branchHomes[branch] = home;
+        if (branch == "") continue;
+        QSet<int> taken;
+        taken.insert(0);
+        Range myRange = m_branchRanges[branch];
+        foreach (QString other, m_branchRanges.keys()) {
+            if (other == branch || other == "") continue;
+            Range otherRange = m_branchRanges[other];
+            if (rangesConflict(myRange, otherRange)) {
+                if (m_branchHomes.contains(other)) {
+                    taken.insert(m_branchHomes[other]);
+                }
+            }
+        }
+        int home = 2;
+        while (taken.contains(home)) {
+            if (home > 0) {
+                if (home % 2 == 1) {
+                    home = -home;
+                } else {
+                    home = home + 1;
+                }
+            } else {
+                if ((-home) % 2 == 1) {
+                    home = home + 1;
+                } else {
+                    home = -(home-2);
+                }
+            }
+        }
+        m_branchHomes[branch] = home;
     }
 
     foreach (QString branch, m_branchRanges.keys()) {
-	std::cerr << branch.toStdString() << ": " << m_branchRanges[branch].first << " - " << m_branchRanges[branch].second << ", home " << m_branchHomes[branch] << std::endl;
+        std::cerr << branch.toStdString() << ": " << m_branchRanges[branch].first << " - " << m_branchRanges[branch].second << ", home " << m_branchHomes[branch] << std::endl;
     }
 }
 
 static bool
-compareChangesetsByDate(Changeset *const &a, Changeset *const &b)
+        compareChangesetsByDate(Changeset *const &a, Changeset *const &b)
 {
     return a->timestamp() < b->timestamp();
 }
 
 ChangesetItem *
-Grapher::getItemFor(Changeset *cs)
+        Grapher::getItemFor(Changeset *cs)
 {
     if (!cs || !m_items.contains(cs->id())) return 0;
     return m_items[cs->id()];
 }
 
-void
-Grapher::layout(Changesets csets)
+void Grapher::layout(Changesets csets)
 {
     m_changesets.clear();
     m_items.clear();
@@ -334,41 +328,41 @@
 
     foreach (Changeset *cs, csets) {
 
-	QString id = cs->id();
-	std::cerr << id.toStdString() << std::endl;
+        QString id = cs->id();
+        std::cerr << id.toStdString() << std::endl;
 
-	if (id == "") {
-	    throw LayoutException("Changeset has no ID");
-	}
-	if (m_changesets.contains(id)) {
-	    throw LayoutException(QString("Duplicate changeset ID %1").arg(id));
-	}
+        if (id == "") {
+            throw LayoutException("Changeset has no ID");
+        }
+        if (m_changesets.contains(id)) {
+            throw LayoutException(QString("Duplicate changeset ID %1").arg(id));
+        }
 
-	m_changesets[id] = cs;
+        m_changesets[id] = cs;
 
         ChangesetItem *item = new ChangesetItem(cs);
         item->setX(0);
         item->setY(0);
-	m_items[id] = item;
+        m_items[id] = item;
         m_scene->addItem(item);
     }
 
     // Add the connecting lines
 
     foreach (Changeset *cs, csets) {
-	QString id = cs->id();
-	ChangesetItem *item = m_items[id];
-	bool merge = (cs->parents().size() > 1);
-	foreach (QString parentId, cs->parents()) {
-	    if (!m_changesets.contains(parentId)) continue;
-	    Changeset *parent = m_changesets[parentId];
-	    parent->addChild(id);
-	    ConnectionItem *conn = new ConnectionItem();
-	    if (merge) conn->setConnectionType(ConnectionItem::Merge);
-	    conn->setChild(item);
-	    conn->setParent(m_items[parentId]);
-	    m_scene->addItem(conn);
-	}
+        QString id = cs->id();
+        ChangesetItem *item = m_items[id];
+        bool merge = (cs->parents().size() > 1);
+        foreach (QString parentId, cs->parents()) {
+            if (!m_changesets.contains(parentId)) continue;
+            Changeset *parent = m_changesets[parentId];
+            parent->addChild(id);
+            ConnectionItem *conn = new ConnectionItem();
+            if (merge) conn->setConnectionType(ConnectionItem::Merge);
+            conn->setChild(item);
+            conn->setParent(m_items[parentId]);
+            m_scene->addItem(conn);
+        }
     }
 
     // Add the branch labels
@@ -396,33 +390,33 @@
     qStableSort(csets.begin(), csets.end(), compareChangesetsByDate);
 
     foreach (Changeset *cs, csets) {
-	std::cerr << "id " << cs->id().toStdString() << ", ts " << cs->timestamp() << ", date " << cs->datetime().toStdString() << std::endl;
+        std::cerr << "id " << cs->id().toStdString() << ", ts " << cs->timestamp() << ", date " << cs->datetime().toStdString() << std::endl;
     }
 
     m_handled.clear();
     foreach (Changeset *cs, csets) {
-	layoutRow(cs->id());
+        layoutRow(cs->id());
     }
 
     allocateBranchHomes(csets);
 
     m_handled.clear();
     foreach (Changeset *cs, csets) {
-	foreach (QString parentId, cs->parents()) {
-	    if (!m_handled.contains(parentId) &&
-		m_changesets.contains(parentId)) {
-		layoutCol(parentId);
-	    }
-	}
-	layoutCol(cs->id());
+        foreach (QString parentId, cs->parents()) {
+            if (!m_handled.contains(parentId) &&
+                m_changesets.contains(parentId)) {
+                layoutCol(parentId);
+            }
+        }
+        layoutCol(cs->id());
     }
 
     foreach (Changeset *cs, csets) {
-	ChangesetItem *item = m_items[cs->id()];
-	if (!m_alloc[item->row()].contains(item->column()-1) &&
-	    !m_alloc[item->row()].contains(item->column()+1)) {
-	    item->setWide(true);
-	}
+        ChangesetItem *item = m_items[cs->id()];
+        if (!m_alloc[item->row()].contains(item->column()-1) &&
+            !m_alloc[item->row()].contains(item->column()+1)) {
+            item->setWide(true);
+        }
     }
 
     // we know that 0 is an upper bound on row, and that mincol must
@@ -431,13 +425,13 @@
     int mincol = 0, maxcol = 0;
 
     foreach (int r, m_alloc.keys()) {
-	if (r < minrow) minrow = r;
-	if (r > maxrow) maxrow = r;
-	ColumnSet &c = m_alloc[r];
-	foreach (int i, c) {
-	    if (i < mincol) mincol = i;
-	    if (i > maxcol) maxcol = i;
-	}
+        if (r < minrow) minrow = r;
+        if (r > maxrow) maxrow = r;
+        ColumnSet &c = m_alloc[r];
+        foreach (int i, c) {
+            if (i < mincol) mincol = i;
+            if (i > maxcol) maxcol = i;
+        }
     }
 
     QString prevDate;
@@ -447,36 +441,36 @@
     int n = 0;
 
     for (int row = minrow; row <= maxrow; ++row) {
-	
-	QString date = m_rowDates[row];
-	n++;
 
-	if (date != prevDate) {
-	    if (prevDate != "") {
-		DateItem *item = new DateItem();
-		item->setDateString(prevDate);
-		item->setCols(mincol, maxcol - mincol + 1);
-		item->setRows(changeRow, n);
-		item->setEven(even);
-		item->setZValue(-1);
-		m_scene->addItem(item);
-		even = !even;
-	    }
-	    prevDate = date;
-	    changeRow = row;
-	    n = 0;
-	}
+        QString date = m_rowDates[row];
+        n++;
+
+        if (date != prevDate) {
+            if (prevDate != "") {
+                DateItem *item = new DateItem();
+                item->setDateString(prevDate);
+                item->setCols(mincol, maxcol - mincol + 1);
+                item->setRows(changeRow, n);
+                item->setEven(even);
+                item->setZValue(-1);
+                m_scene->addItem(item);
+                even = !even;
+            }
+            prevDate = date;
+            changeRow = row;
+            n = 0;
+        }
     }
     
     if (n > 0) {
-	DateItem *item = new DateItem();
-	item->setDateString(prevDate);
-	item->setCols(mincol, maxcol - mincol + 1);
-	item->setRows(changeRow, n+1);
-	item->setEven(even);
-	item->setZValue(-1);
-	m_scene->addItem(item);
-	even = !even;
+        DateItem *item = new DateItem();
+        item->setDateString(prevDate);
+        item->setCols(mincol, maxcol - mincol + 1);
+        item->setRows(changeRow, n+1);
+        item->setEven(even);
+        item->setZValue(-1);
+        m_scene->addItem(item);
+        even = !even;
     }
 }