changeset 146:5e16b83374fd

* Merge
author Chris Cannam
date Wed, 01 Dec 2010 17:43:43 +0000
parents 644bd31e8301 (diff) 0ad212075b36 (current diff)
children 465c8d51c6d5
files
diffstat 13 files changed, 212 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/changesetitem.cpp	Wed Dec 01 12:02:06 2010 +0000
+++ b/changesetitem.cpp	Wed Dec 01 17:43:43 2010 +0000
@@ -188,7 +188,7 @@
         paint->drawRect(QRectF(x0 - 4, -4, width + 5, height + 8));
     }
 
-    if (scale < 0.1) {
+    if (scale < 0.2) {
 	paint->restore();
 	return;
     }
--- a/connectionitem.cpp	Wed Dec 01 12:02:06 2010 +0000
+++ b/connectionitem.cpp	Wed Dec 01 17:43:43 2010 +0000
@@ -16,6 +16,7 @@
 */
 
 #include "connectionitem.h"
+#include "uncommitteditem.h"
 
 #include "changesetitem.h"
 #include "changeset.h"
@@ -26,33 +27,49 @@
 QRectF
 ConnectionItem::boundingRect() const
 {
-    if (!m_parent || !m_child) return QRectF();
+    if (!m_parent || !(m_child || m_uncommitted)) return QRectF();
     float xscale = 100;
     float yscale = 90;
     float size = 50;
-    return QRectF(xscale * m_child->column() + size/2 - 2,
-		  yscale * m_child->row() + size - 2,
-		  xscale * m_parent->column() - xscale * m_child->column() + 4,
-		  yscale * m_parent->row() - yscale * m_child->row() - size + 4)
+
+    int p_col = m_parent->column(), p_row = m_parent->row();
+    int c_col, c_row;
+    if (m_child) {
+        c_col = m_child->column(); c_row = m_child->row();
+    } else {
+        c_col = m_uncommitted->column(); c_row = m_uncommitted->row();
+    }
+
+    return QRectF(xscale * c_col + size/2 - 2,
+		  yscale * c_row + size - 2,
+		  xscale * p_col - xscale * c_col + 4,
+		  yscale * p_row - yscale * c_row - size + 4)
 	.normalized();
 }
 
 void
 ConnectionItem::paint(QPainter *paint, const QStyleOptionGraphicsItem *, QWidget *)
 {
+    if (!m_parent || !(m_child || m_uncommitted)) return;
     QPainterPath p;
 
     paint->save();
 
     ColourSet *colourSet = ColourSet::instance();
-    QColor branchColour = colourSet->getColourFor(m_child->getChangeset()->branch());
+    QString branch;
+    if (m_child) branch = m_child->getChangeset()->branch();
+    else branch = m_uncommitted->branch();
+    QColor branchColour = colourSet->getColourFor(branch);
+
+    Qt::PenStyle ls = Qt::SolidLine;
+    if (!m_child) ls = Qt::DashLine;
 
     QTransform t = paint->worldTransform();
     float scale = std::min(t.m11(), t.m22());
-    if (scale < 0.1) {
-	paint->setPen(QPen(branchColour, 0));
+    if (scale < 0.2) {
+	paint->setPen(QPen(branchColour, 0, ls));
     } else {
-	paint->setPen(QPen(branchColour, 2));
+	paint->setPen(QPen(branchColour, 2, ls));
     }
 
     float xscale = 100;
@@ -61,8 +78,13 @@
     float size = 50;
     float ygap = yscale - size;
 
-    int c_col = m_child->column(), c_row = m_child->row();
     int p_col = m_parent->column(), p_row = m_parent->row();
+    int c_col, c_row;
+    if (m_child) {
+        c_col = m_child->column(); c_row = m_child->row();
+    } else {
+        c_col = m_uncommitted->column(); c_row = m_uncommitted->row();
+    }
 
     float c_x = xscale * c_col + size/2;
     float p_x = xscale * p_col + size/2;
--- a/connectionitem.h	Wed Dec 01 12:02:06 2010 +0000
+++ b/connectionitem.h	Wed Dec 01 17:43:43 2010 +0000
@@ -23,6 +23,7 @@
 class Connection;
 
 class ChangesetItem;
+class UncommittedItem;
 
 class ConnectionItem : public QGraphicsItem
 {
@@ -41,18 +42,20 @@
     Type connectionType() const { return m_type; }
     void setConnectionType(Type t) { m_type = t; }
 
-    //!!! deletion signals from parent/child
+    //!!! deletion signals from parent/child?
 
     ChangesetItem *parent() { return m_parent; }
     ChangesetItem *child() { return m_child; }
 
     void setParent(ChangesetItem *p) { m_parent = p; }
     void setChild(ChangesetItem *c) { m_child = c; }
+    void setChild(UncommittedItem *u) { m_uncommitted = u; }
 
 private:
     Type m_type;
     ChangesetItem *m_parent;
     ChangesetItem *m_child;
+    UncommittedItem *m_uncommitted;
 };
 
 #endif // CONNECTIONITEM_H
--- a/grapher.cpp	Wed Dec 01 12:02:06 2010 +0000
+++ b/grapher.cpp	Wed Dec 01 17:43:43 2010 +0000
@@ -27,24 +27,30 @@
 {
     int col = parent;
     if (preferParentCol) {
-        if (!m_alloc[row].contains(col)) {
-            return col;
-        }
+        if (isAvailable(row, col)) return col;
     }
     while (col > 0) {
-        if (!m_alloc[row].contains(--col)) return col;
+        if (isAvailable(row, --col)) return col;
     }
     while (col < 0) {
-        if (!m_alloc[row].contains(++col)) return col;
+        if (isAvailable(row, ++col)) return col;
     }
     col = parent;
     int sign = (col < 0 ? -1 : 1);
     while (1) {
         col += sign;
-        if (!m_alloc[row].contains(col)) return col;
+        if (isAvailable(row, col)) return col;
     }
 }
 
+bool Grapher::isAvailable(int row, int col)
+{
+    if (m_alloc.contains(row) && m_alloc[row].contains(col)) return false;
+    if (!m_haveAllocatedUncommittedColumn) return true;
+    if (!m_uncommitted) return true;
+    return !(row <= m_uncommittedParentRow && col == m_uncommitted->column());
+}
+
 void Grapher::layoutRow(QString id)
 {
     if (m_handled.contains(id)) {
@@ -102,6 +108,12 @@
         m_rowDates[row] = date;
     }
 
+    // If we're the parent of the uncommitted item, make a note of our
+    // row (we need it later, to avoid overwriting the connecting line)
+    if (m_uncommittedParentId == id) {
+        m_uncommittedParentRow = row;
+    }
+
     DEBUG << "putting " << cs->id().toStdString() << " at row " << row 
           << endl;
 
@@ -186,6 +198,15 @@
     item->setColumn(col);
     m_handled.insert(id);
 
+    // If we're the parent of the uncommitted item, it should be given
+    // the same column as us (ideally)
+
+    if (m_uncommittedParentId == id) {
+        int ucol = findAvailableColumn(row-1, col, true);
+        m_uncommitted->setColumn(ucol);
+        m_haveAllocatedUncommittedColumn = true;
+    }
+
     // Normally the children will lay out themselves, but we can do
     // a better job in some special cases:
 
@@ -306,39 +327,46 @@
 }
 
 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, QString uncommittedSproutsFrom)
 {
     m_changesets.clear();
     m_items.clear();
     m_alloc.clear();
     m_branchHomes.clear();
 
+    m_uncommittedParentId = uncommittedSproutsFrom;
+    m_haveAllocatedUncommittedColumn = false;
+    m_uncommittedParentRow = 0;
+    m_uncommitted = 0;
+
     DEBUG << "Grapher::layout: Have " << csets.size() << " changesets" << endl;
 
     if (csets.empty()) return;
 
+    // Create (but don't yet position) the changeset items
+
     foreach (Changeset *cs, csets) {
 
         QString id = cs->id();
-//        DEBUG << id.toStdString() << endl;
 
         if (id == "") {
             throw LayoutException("Changeset has no ID");
         }
         if (m_changesets.contains(id)) {
-            DEBUG << "Duplicate changeset ID " << id << " in Grapher::layout()" << endl;
+            DEBUG << "Duplicate changeset ID " << id
+                  << " in Grapher::layout()" << endl;
             throw LayoutException(QString("Duplicate changeset ID %1").arg(id));
         }
 
@@ -368,8 +396,20 @@
             m_scene->addItem(conn);
         }
     }
+    
+    // Add uncommitted item and connecting line as necessary
+
+    if (m_uncommittedParentId != "") {
+        m_uncommitted = new UncommittedItem();
+        m_scene->addItem(m_uncommitted);
+        ConnectionItem *conn = new ConnectionItem();
+        conn->setParent(m_items[m_uncommittedParentId]);
+        conn->setChild(m_uncommitted);
+        m_scene->addItem(conn);
+    }
 
     // Add the branch labels
+
     foreach (Changeset *cs, csets) {
         QString id = cs->id();
         ChangesetItem *item = m_items[id];
@@ -394,7 +434,8 @@
     qStableSort(csets.begin(), csets.end(), compareChangesetsByDate);
 
     foreach (Changeset *cs, csets) {
-        DEBUG << "id " << cs->id().toStdString() << ", ts " << cs->timestamp() << ", date " << cs->datetime().toStdString() << endl;
+        DEBUG << "id " << cs->id().toStdString() << ", ts " << cs->timestamp()
+              << ", date " << cs->datetime().toStdString() << endl;
     }
 
     m_handled.clear();
@@ -415,16 +456,10 @@
         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);
-        }
-    }
+    // Find row and column extents.  We know that 0 is an upper bound
+    // on row, and that mincol must be <= 0 and maxcol >= 0, so these
+    // initial values are good
 
-    // we know that 0 is an upper bound on row, and that mincol must
-    // be <= 0 and maxcol >= 0, so these initial values are good
     int minrow = 0, maxrow = 0;
     int mincol = 0, maxcol = 0;
 
@@ -438,12 +473,44 @@
         }
     }
 
+    // We've given the uncommitted item a column, but not a row yet --
+    // it always goes at the top
+
+    if (m_uncommitted) {
+        --minrow;
+        DEBUG << "putting uncommitted item at row " << minrow << endl;
+        m_uncommitted->setRow(minrow);
+    }
+
+    // Changeset items that have nothing to either side of them can be
+    // made double-width
+
+    foreach (Changeset *cs, csets) {
+        ChangesetItem *item = m_items[cs->id()];
+        if (isAvailable(item->row(), item->column()-1) &&
+            isAvailable(item->row(), item->column()+1)) {
+            item->setWide(true);
+        }
+    }
+
+    if (m_uncommitted) {
+        if (isAvailable(m_uncommitted->row(), m_uncommitted->column()-1) &&
+            isAvailable(m_uncommitted->row(), m_uncommitted->column()+1)) {
+            m_uncommitted->setWide(true);
+        }
+    }
+
     QString prevDate;
     int changeRow = 0;
 
     bool even = false;
     int n = 0;
 
+    if (mincol == maxcol) {
+        --mincol;
+        ++maxcol;
+    }
+
     for (int row = minrow; row <= maxrow; ++row) {
 
         QString date = m_rowDates[row];
--- a/grapher.h	Wed Dec 01 12:02:06 2010 +0000
+++ b/grapher.h	Wed Dec 01 17:43:43 2010 +0000
@@ -20,6 +20,7 @@
 
 #include "changeset.h"
 #include "changesetitem.h"
+#include "uncommitteditem.h"
 #include "changesetscene.h"
 
 #include <QSet>
@@ -33,10 +34,12 @@
 public:
     Grapher(ChangesetScene *scene) { m_scene = scene; }
 
-    void layout(Changesets csets);
+    void layout(Changesets csets, QString uncommittedSproutsFrom = "");
 
     ChangesetItem *getItemFor(Changeset *cs);
 
+    UncommittedItem *getUncommittedItem() { return m_uncommitted; }
+
     class LayoutException : public std::exception {
     public:
 	LayoutException(QString message) throw() : m_message(message) { }
@@ -74,11 +77,17 @@
     typedef QMap<int, QString> RowDateMap;
     RowDateMap m_rowDates;
 
+    QString m_uncommittedParentId;
+    int m_uncommittedParentRow;
+    UncommittedItem *m_uncommitted;
+    bool m_haveAllocatedUncommittedColumn;
+
     void layoutRow(QString id);
     void layoutCol(QString id);
     void allocateBranchHomes(Changesets csets);
     bool rangesConflict(const Range &r1, const Range &r2);
     int findAvailableColumn(int row, int parent, bool preferParentCol);
+    bool isAvailable(int row, int col);
 };
 
 #endif 
--- a/hgtabwidget.cpp	Wed Dec 01 12:02:06 2010 +0000
+++ b/hgtabwidget.cpp	Wed Dec 01 17:43:43 2010 +0000
@@ -73,14 +73,9 @@
     m_fileStatusWidget->clearSelections();
 }
 
-void HgTabWidget::setCurrent(QStringList ids)
+void HgTabWidget::setCurrent(QStringList ids, bool showUncommittedChanges)
 {
-    m_historyWidget->setCurrent(ids);
-}
-
-void HgTabWidget::showUncommittedChanges(bool u)
-{
-    m_historyWidget->showUncommittedChanges(u);
+    m_historyWidget->setCurrent(ids, showUncommittedChanges);
 }
 
 bool HgTabWidget::canCommit() const
--- a/hgtabwidget.h	Wed Dec 01 12:02:06 2010 +0000
+++ b/hgtabwidget.h	Wed Dec 01 17:43:43 2010 +0000
@@ -48,8 +48,7 @@
     void setWorkFolderAndRepoNames(QString workFolderPath, QString remoteRepoPath);
     void setState(QString state);
 
-    void setCurrent(QStringList ids);
-    void showUncommittedChanges(bool);
+    void setCurrent(QStringList ids, bool showUncommittedChanges);
 
     FileStates getFileStates() { return m_fileStates; }
 
--- a/historywidget.cpp	Wed Dec 01 12:02:06 2010 +0000
+++ b/historywidget.cpp	Wed Dec 01 17:43:43 2010 +0000
@@ -32,9 +32,6 @@
 {
     m_panned = new Panned;
     m_panner = new Panner;
-    m_uncommitted = new UncommittedItem();
-    m_uncommitted->setRow(-1);
-    m_uncommittedVisible = false;
 
     QGridLayout *layout = new QGridLayout;
     layout->addWidget(m_panned, 0, 0);
@@ -48,7 +45,11 @@
 HistoryWidget::~HistoryWidget()
 {
     clearChangesets();
-    if (!m_uncommittedVisible) delete m_uncommitted;
+}
+
+QGraphicsScene *HistoryWidget::scene()
+{
+    return m_panned->scene();
 }
 
 void HistoryWidget::clearChangesets()
@@ -57,29 +58,25 @@
     m_changesets.clear();
 }
 
-void HistoryWidget::setCurrent(QStringList ids)
+void HistoryWidget::setCurrent(QStringList ids, bool showUncommitted)
 {
-    if (m_currentIds == ids) return;
-    DEBUG << "HistoryWidget::setCurrent: " << ids.size() << " ids" << endl;
+    if (m_currentIds == ids && m_showUncommitted == showUncommitted) return;
+
+    DEBUG << "HistoryWidget::setCurrent: " << ids.size() << " ids, "
+          << "showUncommitted: " << showUncommitted << endl;
+
     m_currentIds.clear();
+    m_uncommittedParentId = "";
+    m_showUncommitted = showUncommitted;
+
+    if (ids.empty()) return;
+
     foreach (QString id, ids) {
         m_currentIds.push_back(id);
     }
-    updateNewAndCurrentItems();
-}
 
-void HistoryWidget::showUncommittedChanges(bool show)
-{
-    if (m_uncommittedVisible == show) return;
-    m_uncommittedVisible = show;
-    ChangesetScene *scene = qobject_cast<ChangesetScene *>(m_panned->scene());
-    if (!scene) return;
-    if (m_uncommittedVisible) {
-        scene->addUncommittedItem(m_uncommitted);
-        m_uncommitted->ensureVisible();
-    } else {
-        scene->removeItem(m_uncommitted);
-    }
+    if (m_showUncommitted) m_uncommittedParentId = m_currentIds[0];
+    layoutAll();
 }
     
 void HistoryWidget::parseNewLog(QString log)
@@ -152,30 +149,24 @@
 
     QGraphicsScene *oldScene = m_panned->scene();
 
-    // detach m_uncommitted from old scene so it doesn't get deleted
-    if (oldScene && (m_uncommitted->scene() == oldScene)) {
-        oldScene->removeItem(m_uncommitted);
-    }
-
     m_panned->setScene(0);
     m_panner->setScene(0);
 
     delete oldScene;
 
+    QGraphicsItem *toFocus = 0;
+
     if (!m_changesets.empty()) {
 	Grapher g(scene);
 	try {
-	    g.layout(m_changesets);
+	    g.layout(m_changesets, m_uncommittedParentId);
 	} catch (std::string s) {
 	    std::cerr << "Internal error: Layout failed: " << s << std::endl;
 	}
-	tipItem = g.getItemFor(m_changesets[0]);
-        DEBUG << "tipItem is " << tipItem << " for tip changeset " 
-              << m_changesets[0]->id() << endl;
-    }
-
-    if (m_uncommittedVisible) {
-        scene->addUncommittedItem(m_uncommitted);
+        toFocus = g.getUncommittedItem();
+        if (!toFocus) {
+            toFocus = g.getItemFor(m_changesets[0]);
+        }
     }
 
     m_panned->setScene(scene);
@@ -183,12 +174,8 @@
 
     updateNewAndCurrentItems();
 
-    if (m_uncommittedVisible) {
-        DEBUG << "asking uncommitted item to be visible" << endl;
-        m_uncommitted->ensureVisible();
-    } else if (tipItem) {
-        DEBUG << "asking tip item to be visible" << endl;
-        tipItem->ensureVisible();
+    if (toFocus) {
+        toFocus->ensureVisible();
     }
 
     connectSceneSignals();
@@ -237,13 +224,6 @@
         
         csit->setCurrent(current);
         csit->setNew(newid);
-        
-        if (current) {
-            m_uncommitted->setRow(csit->row() - 1);
-            m_uncommitted->setColumn(csit->column());
-            m_uncommitted->setWide(csit->isWide());
-            m_uncommitted->setBranch(csit->getChangeset()->branch());
-        }
     }
 }
 
--- a/historywidget.h	Wed Dec 01 12:02:06 2010 +0000
+++ b/historywidget.h	Wed Dec 01 17:43:43 2010 +0000
@@ -26,6 +26,7 @@
 class Panned;
 class Panner;
 class UncommittedItem;
+class QGraphicsScene;
 
 class HistoryWidget : public QWidget
 {
@@ -35,8 +36,7 @@
     HistoryWidget();
     virtual ~HistoryWidget();
 
-    void setCurrent(QStringList ids);
-    void showUncommittedChanges(bool);
+    void setCurrent(QStringList ids, bool showUncommitted);
 
     void parseNewLog(QString log);
     void parseIncrementalLog(QString log);
@@ -58,12 +58,13 @@
     Changesets m_changesets;
     QStringList m_currentIds;
     QSet<QString> m_newIds;
-    UncommittedItem *m_uncommitted;
-    bool m_uncommittedVisible;
+    bool m_showUncommitted;
+    QString m_uncommittedParentId;
 
     Panned *m_panned;
     Panner *m_panner;
 
+    QGraphicsScene *scene();
     void clearChangesets();
     void replaceChangesets(Changesets);
     void addChangesets(Changesets);
--- a/main.cpp	Wed Dec 01 12:02:06 2010 +0000
+++ b/main.cpp	Wed Dec 01 17:43:43 2010 +0000
@@ -15,12 +15,13 @@
     COPYING included with this distribution for more information.
 */
 
-#include <QApplication>
-
 #include "mainwindow.h"
 #include "common.h"
 #include "debug.h"
 
+#include <QApplication>
+#include <QDir>
+
 int main(int argc, char *argv[])
 {
     QApplication::setOrganizationName("easymercurial");
@@ -34,7 +35,18 @@
     installSignalHandlers();
 
     QApplication app(argc, argv);
+    QStringList args = app.arguments();
     MainWindow mainWin;
     mainWin.show();
+
+    if (args.size() == 2) {
+        QString path = args[1];
+        DEBUG << "Opening " << args[1] << endl;
+        if (QDir(path).exists()) {
+            path = QDir(path).canonicalPath();
+            mainWin.open(path);
+        }
+    }
+
     return app.exec();
 }
--- a/mainwindow.cpp	Wed Dec 01 12:02:06 2010 +0000
+++ b/mainwindow.cpp	Wed Dec 01 17:43:43 2010 +0000
@@ -743,6 +743,15 @@
     }
 }
 
+void MainWindow::open(QString local)
+{
+    if (openLocal(local)) {
+        enableDisableActions();
+        clearState();
+        hgQueryPaths();
+    }
+}
+
 bool MainWindow::complainAboutFilePath(QString arg)
 {    
     QMessageBox::critical
@@ -1435,8 +1444,8 @@
 
     QDir localRepoDir;
     QDir workFolderDir;
-    bool workFolderExist;
-    bool localRepoExist;
+    bool workFolderExist = true;
+    bool localRepoExist = true;
 
     remoteRepoActionsEnabled = true;
     if (remoteRepoPath.isEmpty()) {
@@ -1544,8 +1553,7 @@
 
     QStringList ids;
     foreach (Changeset *cs, currentParents) ids.push_back(cs->id());
-    hgTabs->setCurrent(ids);
-    hgTabs->showUncommittedChanges(hgTabs->canCommit());
+    hgTabs->setCurrent(ids, hgTabs->canCommit());
 
     // Set the state field on the file status widget
 
--- a/mainwindow.h	Wed Dec 01 12:02:06 2010 +0000
+++ b/mainwindow.h	Wed Dec 01 17:43:43 2010 +0000
@@ -56,6 +56,7 @@
     void closeEvent(QCloseEvent *event);
 
 public slots:
+    void open(QString local);
     void hgRefresh();
     void commandCompleted(HgAction action, QString stdOut);
     void commandFailed(HgAction action, QString stdErr);
--- a/uncommitteditem.cpp	Wed Dec 01 12:02:06 2010 +0000
+++ b/uncommitteditem.cpp	Wed Dec 01 17:43:43 2010 +0000
@@ -113,10 +113,21 @@
     QRectF r(x0, 0, width - 3, height);
     paint->drawRect(r);
 
-    paint->drawLine(x0 + width/2, height, x0 + width/2, height + 40);
-
-    QString label = tr("Uncommitted changes");
-    paint->drawText(-(fm.width(label) - 50)/2, 25 - fm.height()/2 + fm.ascent(), label);
+    if (m_wide) {
+        QString label = tr("Uncommitted changes");
+        paint->drawText(-(fm.width(label) - 50)/2,
+                        25 - fm.height()/2 + fm.ascent(),
+                        label);
+    } else {
+        QString label = tr("Uncommitted");
+        paint->drawText(-(fm.width(label) - 50)/2,
+                        25 - fm.height() + fm.ascent(),
+                        label);
+        label = tr("changes");
+        paint->drawText(-(fm.width(label) - 50)/2,
+                        25 + fm.ascent(),
+                        label);
+    }        
 
     paint->restore();
     return;