# HG changeset patch # User Chris Cannam # Date 1318885685 -3600 # Node ID 470829a21f98a8e5d68bfffd16d02b207975045a # Parent 1c05e7576ea579896a3831e91b826c09e3bb28f3 Identify closed branches and display them in a lighter shade diff -r 1c05e7576ea5 -r 470829a21f98 src/changesetitem.cpp --- a/src/changesetitem.cpp Mon Oct 17 16:25:02 2011 +0100 +++ b/src/changesetitem.cpp Mon Oct 17 22:08:05 2011 +0100 @@ -38,7 +38,7 @@ ChangesetItem::ChangesetItem(Changeset *cs) : m_changeset(cs), m_detail(0), m_showBranch(false), m_column(0), m_row(0), m_wide(false), - m_current(false), m_new(false) + m_current(false), m_closed(false), m_new(false) { m_font = QFont(); m_font.setPixelSize(11); @@ -262,10 +262,16 @@ { paint->save(); + int alpha = 255; + if (m_closed) alpha = 90; + ColourSet *colourSet = ColourSet::instance(); QColor branchColour = colourSet->getColourFor(m_changeset->branch()); QColor userColour = colourSet->getColourFor(m_changeset->author()); + branchColour.setAlpha(alpha); + userColour.setAlpha(alpha); + QFont f(m_font); QTransform t = paint->worldTransform(); @@ -363,7 +369,10 @@ fm, textwid); paint->drawText(x0 + 3, fm.ascent(), person); - paint->setPen(QPen(Qt::black)); + QColor textColour = Qt::black; + textColour.setAlpha(alpha); + + paint->setPen(QPen(textColour)); QStringList tags = m_changeset->tags(); if (!tags.empty()) { @@ -427,11 +436,17 @@ ChangesetItem::paintMerge(QPainter *paint) { paint->save(); + + int alpha = 255; + if (m_closed) alpha = 40; ColourSet *colourSet = ColourSet::instance(); QColor branchColour = colourSet->getColourFor(m_changeset->branch()); QColor userColour = colourSet->getColourFor(m_changeset->author()); + branchColour.setAlpha(alpha); + userColour.setAlpha(alpha); + QFont f(m_font); QTransform t = paint->worldTransform(); diff -r 1c05e7576ea5 -r 470829a21f98 src/changesetitem.h --- a/src/changesetitem.h Mon Oct 17 16:25:02 2011 +0100 +++ b/src/changesetitem.h Mon Oct 17 22:08:05 2011 +0100 @@ -51,6 +51,9 @@ bool isCurrent() const { return m_current; } void setCurrent(bool c) { m_current = c; } + bool isClosed() const { return m_closed; } + void setClosed(bool c) { m_closed = c; } + bool isNew() const { return m_new; } void setNew(bool n) { m_new = n; } @@ -98,6 +101,7 @@ int m_row; bool m_wide; bool m_current; + bool m_closed; bool m_new; QMap m_parentDiffActions; diff -r 1c05e7576ea5 -r 470829a21f98 src/connectionitem.cpp --- a/src/connectionitem.cpp Mon Oct 17 16:25:02 2011 +0100 +++ b/src/connectionitem.cpp Mon Oct 17 22:08:05 2011 +0100 @@ -55,12 +55,17 @@ paint->save(); + int alpha = 255; + if (m_child && m_child->isClosed()) alpha = 90; + ColourSet *colourSet = ColourSet::instance(); QString branch; if (m_child) branch = m_child->getChangeset()->branch(); else branch = m_uncommitted->branch(); QColor branchColour = colourSet->getColourFor(branch); + branchColour.setAlpha(alpha); + Qt::PenStyle ls = Qt::SolidLine; if (!m_child) ls = Qt::DashLine; diff -r 1c05e7576ea5 -r 470829a21f98 src/grapher.cpp --- a/src/grapher.cpp Mon Oct 17 16:25:02 2011 +0100 +++ b/src/grapher.cpp Mon Oct 17 22:08:05 2011 +0100 @@ -435,6 +435,35 @@ } } + // Ensure the closed branches are all marked as closed + + foreach (QString closedId, m_closedIds) { + + if (!m_items.contains(closedId)) continue; + + Changeset *cs = m_changesets[closedId]; + ChangesetItem *item = m_items[closedId]; + + while (cs && item) { + + if (cs->children().size() > 1) { + break; + } + + item->setClosed(true); + + int pcount = cs->parents().size(); + if (pcount >= 1) { + QString pid = cs->parents()[0]; + if (!m_items.contains(pid)) break; + cs = m_changesets[pid]; + item = m_items[pid]; + } else { + item = 0; + } + } + } + // Add uncommitted item and connecting line as necessary if (!m_uncommittedParents.empty()) { diff -r 1c05e7576ea5 -r 470829a21f98 src/grapher.h --- a/src/grapher.h Mon Oct 17 16:25:02 2011 +0100 +++ b/src/grapher.h Mon Oct 17 22:08:05 2011 +0100 @@ -43,6 +43,8 @@ UncommittedItem *getUncommittedItem() { return m_uncommitted; } + void setClosedHeadIds(QSet closed) { m_closedIds = closed; } + class LayoutException : public std::exception { public: LayoutException(QString message) throw() : m_message(message) { } @@ -80,6 +82,8 @@ typedef QMap RowDateMap; RowDateMap m_rowDates; + QSet m_closedIds; + bool m_showDates; QStringList m_uncommittedParents; diff -r 1c05e7576ea5 -r 470829a21f98 src/hgaction.h --- a/src/hgaction.h Mon Oct 17 16:25:02 2011 +0100 +++ b/src/hgaction.h Mon Oct 17 22:08:05 2011 +0100 @@ -31,6 +31,7 @@ ACT_STAT, ACT_RESOLVE_LIST, ACT_QUERY_HEADS, + ACT_QUERY_HEADS_ACTIVE, ACT_QUERY_PARENTS, ACT_LOG, ACT_LOG_INCREMENTAL, @@ -92,6 +93,7 @@ case ACT_STAT: case ACT_RESOLVE_LIST: case ACT_QUERY_HEADS: + case ACT_QUERY_HEADS_ACTIVE: case ACT_QUERY_PARENTS: case ACT_LOG_INCREMENTAL: return true; diff -r 1c05e7576ea5 -r 470829a21f98 src/hgtabwidget.cpp --- a/src/hgtabwidget.cpp Mon Oct 17 16:25:02 2011 +0100 +++ b/src/hgtabwidget.cpp Mon Oct 17 22:08:05 2011 +0100 @@ -136,6 +136,11 @@ m_historyWidget->setCurrent(ids, branch, haveChangesToCommit()); } +void HgTabWidget::setClosedHeadIds(QSet closed) +{ + m_historyWidget->setClosedHeadIds(closed); +} + void HgTabWidget::updateFileStates() { m_fileStatusWidget->updateWidgets(); diff -r 1c05e7576ea5 -r 470829a21f98 src/hgtabwidget.h --- a/src/hgtabwidget.h Mon Oct 17 16:25:02 2011 +0100 +++ b/src/hgtabwidget.h Mon Oct 17 22:08:05 2011 +0100 @@ -48,6 +48,7 @@ void setLocalPath(QString workFolderPath); void setCurrent(QStringList ids, QString branch); + void setClosedHeadIds(QSet ids); void setHaveMerge(bool); diff -r 1c05e7576ea5 -r 470829a21f98 src/historywidget.cpp --- a/src/historywidget.cpp Mon Oct 17 16:25:02 2011 +0100 +++ b/src/historywidget.cpp Mon Oct 17 22:08:05 2011 +0100 @@ -87,6 +87,13 @@ m_refreshNeeded = true; } +void HistoryWidget::setClosedHeadIds(QSet closed) +{ + if (closed == m_closedIds) return; + m_closedIds = closed; + m_refreshNeeded = true; +} + void HistoryWidget::setShowUncommitted(bool showUncommitted) { setCurrent(m_currentIds, m_currentBranch, showUncommitted); @@ -181,6 +188,7 @@ if (!m_changesets.empty()) { Grapher g(scene); + g.setClosedHeadIds(m_closedIds); try { g.layout(m_changesets, m_showUncommitted ? m_currentIds : QStringList(), @@ -251,7 +259,8 @@ DEBUG << "id " << id << " is new" << endl; } - if (csit->isCurrent() != current || csit->isNew() != newid) { + if (csit->isCurrent() != current || + csit->isNew() != newid) { csit->setCurrent(current); csit->setNew(newid); csit->update(); diff -r 1c05e7576ea5 -r 470829a21f98 src/historywidget.h --- a/src/historywidget.h Mon Oct 17 16:25:02 2011 +0100 +++ b/src/historywidget.h Mon Oct 17 22:08:05 2011 +0100 @@ -39,6 +39,8 @@ void setCurrent(QStringList ids, QString branch, bool showUncommitted); void setShowUncommitted(bool showUncommitted); + void setClosedHeadIds(QSet closed); + void parseNewLog(QString log); void parseIncrementalLog(QString log); @@ -68,6 +70,7 @@ QStringList m_currentIds; QString m_currentBranch; QSet m_newIds; + QSet m_closedIds; bool m_showUncommitted; bool m_refreshNeeded; diff -r 1c05e7576ea5 -r 470829a21f98 src/mainwindow.cpp --- a/src/mainwindow.cpp Mon Oct 17 16:25:02 2011 +0100 +++ b/src/mainwindow.cpp Mon Oct 17 22:08:05 2011 +0100 @@ -323,6 +323,13 @@ */ } +void MainWindow::hgQueryHeadsActive() +{ + QStringList params; + params << "heads" << "--active"; + m_runner->requestAction(HgAction(ACT_QUERY_HEADS_ACTIVE, m_workFolderPath, params)); +} + void MainWindow::hgQueryHeads() { QStringList params; @@ -1251,6 +1258,7 @@ m_currentParents.clear(); foreach (Changeset *cs, m_currentHeads) delete cs; m_currentHeads.clear(); + m_closedHeadIds.clear(); m_currentBranch = ""; m_lastStatOutput = ""; m_lastRevertedFiles.clear(); @@ -1979,18 +1987,18 @@ bool headsAreLocal = false; if (m_currentParents.size() == 1) { - int m_currentBranchHeads = 0; + int currentBranchActiveHeads = 0; bool parentIsHead = false; Changeset *parent = m_currentParents[0]; - foreach (Changeset *head, m_currentHeads) { + foreach (Changeset *head, m_activeHeads) { if (head->isOnBranch(m_currentBranch)) { - ++m_currentBranchHeads; + ++currentBranchActiveHeads; } if (parent->id() == head->id()) { parentIsHead = true; } } - if (m_currentBranchHeads == 2 && parentIsHead) { + if (currentBranchActiveHeads == 2 && parentIsHead) { headsAreLocal = true; } } @@ -2138,6 +2146,7 @@ return; } break; // go on to default report + case ACT_QUERY_HEADS_ACTIVE: case ACT_QUERY_HEADS: // fails if repo is empty; we don't care (if there's a genuine // problem, something else will fail too). Pretend it @@ -2324,6 +2333,11 @@ } break; + case ACT_QUERY_HEADS_ACTIVE: + foreach (Changeset *cs, m_activeHeads) delete cs; + m_activeHeads = Changeset::parseChangesets(output); + break; + case ACT_QUERY_HEADS: { oldHeadIds = Changeset::getIds(m_currentHeads); @@ -2336,6 +2350,7 @@ headsChanged = true; foreach (Changeset *cs, m_currentHeads) delete cs; m_currentHeads = newHeads; + updateClosedHeads(); } } break; @@ -2486,6 +2501,10 @@ break; case ACT_RESOLVE_LIST: + hgQueryHeadsActive(); + break; + + case ACT_QUERY_HEADS_ACTIVE: hgQueryHeads(); break; @@ -2725,24 +2744,32 @@ bool emptyRepo = false; bool noWorkingCopy = false; bool newBranch = false; - int m_currentBranchHeads = 0; + bool closedBranch = false; + int currentBranchActiveHeads = 0; if (m_currentParents.size() == 1) { bool parentIsHead = false; + bool parentIsActiveHead = false; Changeset *parent = m_currentParents[0]; - foreach (Changeset *head, m_currentHeads) { - DEBUG << "head branch " << head->branch() << ", current branch " << m_currentBranch << endl; + foreach (Changeset *head, m_activeHeads) { if (head->isOnBranch(m_currentBranch)) { - ++m_currentBranchHeads; + ++currentBranchActiveHeads; } if (parent->id() == head->id()) { - parentIsHead = true; + parentIsActiveHead = parentIsHead = true; } } - if (m_currentBranchHeads == 2 && parentIsHead) { + if (!parentIsActiveHead) { + foreach (Changeset *head, m_currentHeads) { + if (parent->id() == head->id()) { + parentIsHead = true; + } + } + } + if (currentBranchActiveHeads == 2 && parentIsActiveHead) { canMerge = true; } - if (m_currentBranchHeads == 0 && parentIsHead) { + if (currentBranchActiveHeads == 0 && parentIsActiveHead) { // Just created a new branch newBranch = true; } @@ -2753,6 +2780,8 @@ foreach (Changeset *h, m_currentHeads) { DEBUG << "head id = " << h->id() << endl; } + } else if (!parentIsActiveHead) { + closedBranch = true; } m_justMerged = false; } else if (m_currentParents.size() == 0) { @@ -2778,9 +2807,9 @@ m_hgPushAct->setEnabled(m_localRepoActionsEnabled && !emptyRepo); m_hgMergeAct->setEnabled(m_localRepoActionsEnabled && - (canMerge || m_hgTabs->canResolve())); + (canMerge || m_hgTabs->canResolve())); m_hgUpdateAct->setEnabled(m_localRepoActionsEnabled && - (canUpdate && !m_hgTabs->haveChangesToCommit())); + (canUpdate && !m_hgTabs->haveChangesToCommit())); // Set the state field on the file status widget @@ -2809,6 +2838,12 @@ m_workStatus->setState(tr("Have merged but not yet committed on %1").arg(branchText)); } else if (newBranch) { m_workStatus->setState(tr("On %1. New branch: has not yet been committed").arg(branchText)); + } else if (closedBranch) { + if (canUpdate) { + m_workStatus->setState(tr("On a closed branch. Not at the head of the branch")); + } else { + m_workStatus->setState(tr("At the head of a closed branch")); + } } else if (canUpdate) { if (m_hgTabs->haveChangesToCommit()) { // have uncommitted changes @@ -2817,14 +2852,29 @@ // no uncommitted changes m_workStatus->setState(tr("On %1. Not at the head of the branch: consider updating").arg(branchText)); } - } else if (m_currentBranchHeads > 1) { - m_workStatus->setState(tr("At one of %n heads of %1", "", m_currentBranchHeads).arg(branchText)); + } else if (currentBranchActiveHeads > 1) { + m_workStatus->setState(tr("At one of %n heads of %1", "", currentBranchActiveHeads).arg(branchText)); } else { m_workStatus->setState(tr("At the head of %1").arg(branchText)); } } +void MainWindow::updateClosedHeads() +{ + m_closedHeadIds.clear(); + QSet activeIds; + foreach (Changeset *cs, m_activeHeads) { + activeIds.insert(cs->id()); + } + foreach (Changeset *cs, m_currentHeads) { + if (!activeIds.contains(cs->id())) { + m_closedHeadIds.insert(cs->id()); + } + } + m_hgTabs->setClosedHeadIds(m_closedHeadIds); +} + void MainWindow::updateRecentMenu() { m_recentMenu->clear(); diff -r 1c05e7576ea5 -r 470829a21f98 src/mainwindow.h --- a/src/mainwindow.h Mon Oct 17 16:25:02 2011 +0100 +++ b/src/mainwindow.h Mon Oct 17 22:08:05 2011 +0100 @@ -121,6 +121,7 @@ private: void hgQueryBranch(); + void hgQueryHeadsActive(); void hgQueryHeads(); void hgQueryParents(); void hgLog(); @@ -178,6 +179,8 @@ void suspendFileSystemWatcher(); void restoreFileSystemWatcher(); + void updateClosedHeads(); + void updateWorkFolderAndRepoNames(); WorkStatusWidget *m_workStatus; @@ -187,6 +190,8 @@ QString m_workFolderPath; QString m_currentBranch; Changesets m_currentHeads; + Changesets m_activeHeads; + QSet m_closedHeadIds; Changesets m_currentParents; int m_commitsSincePush; bool m_stateUnknown;