changeset 52:384420567575

* Use the date when laying out rows
author Chris Cannam
date Fri, 12 Nov 2010 11:32:01 +0000
parents bf3ab0ffb559
children 3c46b2ac45d3
files changeset.h grapher.cpp hgexpwidget.cpp mainwindow.cpp
diffstat 4 files changed, 52 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/changeset.h	Thu Nov 11 22:27:24 2010 +0000
+++ b/changeset.h	Fri Nov 12 11:32:01 2010 +0000
@@ -14,7 +14,8 @@
     Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged STORED true);
     Q_PROPERTY(QString branch READ branch WRITE setBranch NOTIFY branchChanged STORED true);
     Q_PROPERTY(QString tag READ tag WRITE setTag NOTIFY tagChanged STORED true);
-    Q_PROPERTY(QString datetime READ datetime WRITE setdatetime NOTIFY datetimeChanged STORED true);
+    Q_PROPERTY(QString datetime READ datetime WRITE setDatetime NOTIFY datetimeChanged STORED true);
+    Q_PROPERTY(qulonglong timestamp READ timestamp WRITE setTimestamp NOTIFY timestampChanged STORED true);
     Q_PROPERTY(QString age READ age WRITE setAge NOTIFY ageChanged STORED true);
     Q_PROPERTY(QStringList parents READ parents WRITE setParents NOTIFY parentsChanged STORED true);
     Q_PROPERTY(QStringList children READ children WRITE setChildren NOTIFY childrenChanged STORED true);
@@ -28,6 +29,7 @@
     QString branch() const { return m_branch; }
     QString tag() const { return m_tag; }
     QString datetime() const { return m_datetime; }
+    qulonglong timestamp() const { return m_timestamp; }
     QString age() const { return m_age; }
     QStringList parents() const { return m_parents; }
     QStringList children() const { return m_children; }
@@ -52,6 +54,7 @@
     void branchChanged(QString branch);
     void tagChanged(QString tag);
     void datetimeChanged(QString datetime);
+    void timestampChanged(qulonglong timestamp);
     void ageChanged(QString age);
     void parentsChanged(QStringList parents);
     void childrenChanged(QStringList children);
@@ -62,7 +65,8 @@
     void setAuthor(QString author) { m_author = author; emit authorChanged(author); }
     void setBranch(QString branch) { m_branch = branch; emit branchChanged(branch); }
     void setTag(QString tag) { m_tag = tag; emit tagChanged(tag); }
-    void setdatetime(QString datetime) { m_datetime = datetime; emit datetimeChanged(datetime); }
+    void setDatetime(QString datetime) { m_datetime = datetime; emit datetimeChanged(datetime); }
+    void setTimestamp(qulonglong timestamp) { m_timestamp = timestamp; emit timestampChanged(timestamp); }
     void setAge(QString age) { m_age = age; emit ageChanged(age); }
     void setParents(QStringList parents) { m_parents = parents; emit parentsChanged(parents); }
     void setChildren(QStringList children) { m_children = children; emit childrenChanged(m_children); }
@@ -75,6 +79,7 @@
     QString m_branch;
     QString m_tag;
     QString m_datetime;
+    qulonglong m_timestamp;
     QString m_age;
     QStringList m_parents;
     QStringList m_children;
--- a/grapher.cpp	Thu Nov 11 22:27:24 2010 +0000
+++ b/grapher.cpp	Fri Nov 12 11:32:01 2010 +0000
@@ -68,6 +68,28 @@
 	row = row - 1;
     }
 
+    // row is now an upper bound on our eventual row (because we want
+    // to be above all parents).  But we also want to ensure we are
+    // above all nodes that have earlier dates (to the nearest day).
+    // m_rowDates maps each row to a date: use that.
+
+    QString date = cs->date();
+
+    // n.b. this relies on the fact that the date component of an ISO
+    // date/time sorts correctly in a dictionary sort
+    while (m_rowDates.contains(row) && m_rowDates[row] < date) {
+	--row;
+    }
+
+    // We have already laid out all nodes that have earlier timestamps
+    // than this one, so we know (among other things) that we can
+    // safely fill in this row has having this date, if it isn't in
+    // the map yet (it cannot have an earlier date)
+
+    if (!m_rowDates.contains(row)) {
+	m_rowDates[row] = date;
+    }
+
     std::cerr << "putting " << cs->id().toStdString() << " at row " << row 
 	      << std::endl;
 
@@ -178,9 +200,7 @@
         Changeset *child = m_changesets[childId];
         if (child->parents().size() > 1) {
             int childRow = m_items[childId]->row();
-            std::cerr << "I'm at " << row << ", child with >1 parents is at " << childRow << std::endl;
             for (int r = row; r > childRow; --r) {
-                std::cerr << "setting row " << r << ", col " << col << std::endl;
                 m_alloc[r].insert(col);
             }
         }
@@ -201,12 +221,13 @@
 	    }
 	}
 	if (special.size() == 2) {
-	    m_items[special[0]]->setColumn
-		(findAvailableColumn(item->row() - 1, col - 1, true));
-	    m_items[special[1]]->setColumn
-		(findAvailableColumn(item->row() - 1, col + 1, true));
-	    m_handled.insert(special[0]);
-	    m_handled.insert(special[1]);
+	    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));
+		m_alloc[it->row()].insert(it->column());
+		m_handled.insert(special[i]);
+	    }
 	}
     }
 }
@@ -271,6 +292,12 @@
     }
 }
 
+static bool
+compareChangesetsByDate(Changeset *const &a, Changeset *const &b)
+{
+    return a->timestamp() < b->timestamp();
+}
+
 void
 Grapher::layout(Changesets csets)
 {
@@ -314,14 +341,14 @@
 	}
     }
 
-    // Layout in reverse order, i.e. forward chronological order.
-    // This ensures that parents will normally be laid out before
-    // their children -- though we can recurse from layout() if we
-    // find any weird exceptions
+    // We need to lay out the changesets in forward chronological
+    // order.  We have no guarantees about the order in which
+    // changesets appear in the list -- in a simple repository they
+    // will generally be reverse chronological, but that's far from
+    // guaranteed.  So, sort explicitly using the date comparator
+    // above
 
-    //!!! changesets are not in any chronological order, necessarily:
-    // we need to sort by datetime() [or, better, numerical date]
-    // and then use m_rowDateMap
+    qStableSort(csets.begin(), csets.end(), compareChangesetsByDate);
 
     m_handled.clear();
     for (int i = csets.size() - 1; i >= 0; --i) {
--- a/hgexpwidget.cpp	Thu Nov 11 22:27:24 2010 +0000
+++ b/hgexpwidget.cpp	Fri Nov 12 11:32:01 2010 +0000
@@ -348,6 +348,8 @@
 		QStringList parents = e.value(key).split
 		    (" ", QString::SkipEmptyParts);
 		cs->setParents(parents);
+	    } else if (key == "timestamp") {
+		cs->setTimestamp(e.value(key).split(" ")[0].toULongLong());
 	    } else {
 		cs->setProperty(key.toLocal8Bit().data(), e.value(key));
 	    }
--- a/mainwindow.cpp	Thu Nov 11 22:27:24 2010 +0000
+++ b/mainwindow.cpp	Fri Nov 12 11:32:01 2010 +0000
@@ -126,7 +126,7 @@
         QStringList params;
         params << "log";
         params << "--template";
-        params << "id: {rev}:{node|short}\\nauthor: {author}\\nbranch: {branches}\\ntag: {tag}\\ndatetime: {date|isodate}\\nage: {date|age}\\nparents: {parents}\\ncomment: {desc|json}\\n\\n";
+        params << "id: {rev}:{node|short}\\nauthor: {author}\\nbranch: {branches}\\ntag: {tag}\\ndatetime: {date|isodate}\\ntimestamp: {date|hgdate}\\nage: {date|age}\\nparents: {parents}\\ncomment: {desc|json}\\n\\n";
 
         runner -> startProc(getHgBinaryName(), workFolderPath, params);
         runningAction = ACT_LOG;