# HG changeset patch # User Chris Cannam # Date 1291225274 0 # Node ID 644bd31e8301e4856248e9dd202c5a9d4ab272fa # Parent f61f032b06f9ab58e572018688ff7533b2814424 * Include the uncommitted item in general graph layout (in case it is not at the head, when other items will need to avoid it) diff -r f61f032b06f9 -r 644bd31e8301 changesetitem.cpp --- a/changesetitem.cpp Wed Dec 01 11:54:01 2010 +0000 +++ b/changesetitem.cpp Wed Dec 01 17:41:14 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; } diff -r f61f032b06f9 -r 644bd31e8301 connectionitem.cpp --- a/connectionitem.cpp Wed Dec 01 11:54:01 2010 +0000 +++ b/connectionitem.cpp Wed Dec 01 17:41:14 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; diff -r f61f032b06f9 -r 644bd31e8301 connectionitem.h --- a/connectionitem.h Wed Dec 01 11:54:01 2010 +0000 +++ b/connectionitem.h Wed Dec 01 17:41:14 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 diff -r f61f032b06f9 -r 644bd31e8301 grapher.cpp --- a/grapher.cpp Wed Dec 01 11:54:01 2010 +0000 +++ b/grapher.cpp Wed Dec 01 17:41:14 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]; diff -r f61f032b06f9 -r 644bd31e8301 grapher.h --- a/grapher.h Wed Dec 01 11:54:01 2010 +0000 +++ b/grapher.h Wed Dec 01 17:41:14 2010 +0000 @@ -20,6 +20,7 @@ #include "changeset.h" #include "changesetitem.h" +#include "uncommitteditem.h" #include "changesetscene.h" #include @@ -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 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 diff -r f61f032b06f9 -r 644bd31e8301 hgtabwidget.cpp --- a/hgtabwidget.cpp Wed Dec 01 11:54:01 2010 +0000 +++ b/hgtabwidget.cpp Wed Dec 01 17:41:14 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 diff -r f61f032b06f9 -r 644bd31e8301 hgtabwidget.h --- a/hgtabwidget.h Wed Dec 01 11:54:01 2010 +0000 +++ b/hgtabwidget.h Wed Dec 01 17:41:14 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; } diff -r f61f032b06f9 -r 644bd31e8301 historywidget.cpp --- a/historywidget.cpp Wed Dec 01 11:54:01 2010 +0000 +++ b/historywidget.cpp Wed Dec 01 17:41:14 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(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()); - } } } diff -r f61f032b06f9 -r 644bd31e8301 historywidget.h --- a/historywidget.h Wed Dec 01 11:54:01 2010 +0000 +++ b/historywidget.h Wed Dec 01 17:41:14 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 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); diff -r f61f032b06f9 -r 644bd31e8301 main.cpp --- a/main.cpp Wed Dec 01 11:54:01 2010 +0000 +++ b/main.cpp Wed Dec 01 17:41:14 2010 +0000 @@ -15,12 +15,13 @@ COPYING included with this distribution for more information. */ -#include - #include "mainwindow.h" #include "common.h" #include "debug.h" +#include +#include + 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(); } diff -r f61f032b06f9 -r 644bd31e8301 mainwindow.cpp --- a/mainwindow.cpp Wed Dec 01 11:54:01 2010 +0000 +++ b/mainwindow.cpp Wed Dec 01 17:41:14 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 diff -r f61f032b06f9 -r 644bd31e8301 mainwindow.h --- a/mainwindow.h Wed Dec 01 11:54:01 2010 +0000 +++ b/mainwindow.h Wed Dec 01 17:41:14 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); diff -r f61f032b06f9 -r 644bd31e8301 uncommitteditem.cpp --- a/uncommitteditem.cpp Wed Dec 01 11:54:01 2010 +0000 +++ b/uncommitteditem.cpp Wed Dec 01 17:41:14 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;