changeset 312:f98c8ece3035

Merge from branch "new-branches-with-status-outside-tabs"
author Chris Cannam
date Tue, 01 Mar 2011 14:22:53 +0000
parents b8ed12c2035f (current diff) 4811eb34e819 (diff)
children 4b9656471303
files mainwindow.cpp
diffstat 21 files changed, 382 insertions(+), 156 deletions(-) [+]
line wrap: on
line diff
--- a/changesetitem.cpp	Mon Feb 28 17:35:55 2011 +0000
+++ b/changesetitem.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -189,6 +189,10 @@
 
     menu->addSeparator();
 
+    QAction *branch = menu->addAction(tr("Start new branch..."));
+    branch->setEnabled(m_current);
+    connect(branch, SIGNAL(triggered()), this, SLOT(newBranchActivated()));
+
     QAction *tag = menu->addAction(tr("Add tag..."));
     connect(tag, SIGNAL(triggered()), this, SLOT(tagActivated()));
 
@@ -231,6 +235,7 @@
 void ChangesetItem::diffToCurrentActivated() { emit diffToCurrent(getId()); }
 void ChangesetItem::mergeActivated() { emit mergeFrom(getId()); }
 void ChangesetItem::tagActivated() { emit tag(getId()); }
+void ChangesetItem::newBranchActivated() { emit newBranch(getId()); }
 
 void
 ChangesetItem::paint(QPainter *paint, const QStyleOptionGraphicsItem *, QWidget *)
--- a/changesetitem.h	Mon Feb 28 17:35:55 2011 +0000
+++ b/changesetitem.h	Tue Mar 01 14:22:53 2011 +0000
@@ -65,6 +65,7 @@
     void diffToParent(QString child, QString parent);
     void showSummary(Changeset *);
     void mergeFrom(QString);
+    void newBranch(QString);
     void tag(QString);
 
 public slots:
@@ -79,6 +80,7 @@
     void diffToCurrentActivated();
     void mergeActivated();
     void tagActivated();
+    void newBranchActivated();
 
 protected:
     virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
--- a/changesetscene.cpp	Mon Feb 28 17:35:55 2011 +0000
+++ b/changesetscene.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -51,6 +51,9 @@
     connect(item, SIGNAL(mergeFrom(QString)),
             this, SIGNAL(mergeFrom(QString)));
 
+    connect(item, SIGNAL(newBranch(QString)),
+            this, SIGNAL(newBranch(QString)));
+
     connect(item, SIGNAL(tag(QString)),
             this, SIGNAL(tag(QString)));
 }
@@ -74,6 +77,13 @@
 
     connect(item, SIGNAL(showWork()),
             this, SIGNAL(showWork()));
+
+    connect(item, SIGNAL(newBranch()),
+            this, SIGNAL(newBranch()));
+
+    connect(item, SIGNAL(noBranch()),
+            this, SIGNAL(noBranch()));
+
 }
 
 void
--- a/changesetscene.h	Mon Feb 28 17:35:55 2011 +0000
+++ b/changesetscene.h	Tue Mar 01 14:22:53 2011 +0000
@@ -44,12 +44,15 @@
     void diffWorkingFolder();
     void showSummary();
     void showWork();
+    void newBranch();
+    void noBranch();
 
     void updateTo(QString id);
     void diffToParent(QString id, QString parent);
     void showSummary(Changeset *);
     void diffToCurrent(QString id);
     void mergeFrom(QString id);
+    void newBranch(QString id);
     void tag(QString id);
 
 private slots:
--- a/easyhg.pro	Mon Feb 28 17:35:55 2011 +0000
+++ b/easyhg.pro	Tue Mar 01 14:22:53 2011 +0000
@@ -50,6 +50,7 @@
     uncommitteditem.h \
     settingsdialog.h \
     clickablelabel.h \
+    workstatuswidget.h \
     moreinformationdialog.h
 SOURCES = main.cpp \
     mainwindow.cpp \
@@ -81,6 +82,7 @@
     incomingdialog.cpp \
     uncommitteditem.cpp \
     settingsdialog.cpp \
+    workstatuswidget.cpp \
     moreinformationdialog.cpp
 
 macx-* {
Binary file easyhg_en.qm has changed
--- a/easyhg_en.ts	Mon Feb 28 17:35:55 2011 +0000
+++ b/easyhg_en.ts	Tue Mar 01 14:22:53 2011 +0000
@@ -588,10 +588,10 @@
     </message>
     <message numerus="yes">
         <location filename="mainwindow.cpp" line="308"/>
-        <source>You are about to commit %n file(s).</source>
+        <source>You are about to commit %n file(s) to %1.</source>
         <translation type="unfinished">
-            <numerusform>You are about to commit %n file.</numerusform>
-            <numerusform>You are about to commit %n files.</numerusform>
+            <numerusform>You are about to commit %n file to %1.</numerusform>
+            <numerusform>You are about to commit %n files to %1.</numerusform>
         </translation>
     </message>
     <message>
--- a/filestatuswidget.cpp	Mon Feb 28 17:35:55 2011 +0000
+++ b/filestatuswidget.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -18,7 +18,6 @@
 #include "filestatuswidget.h"
 #include "debug.h"
 #include "multichoicedialog.h"
-#include "clickablelabel.h"
 
 #include <QLabel>
 #include <QListWidget>
@@ -43,40 +42,9 @@
 
     int row = 0;
 
-#ifndef Q_OS_MAC    
-    layout->addItem(new QSpacerItem(1, 1), row, 0);
-    ++row;
-#endif
-
-    layout->addWidget(new QLabel(tr("Local:")), row, 0);
-
-    m_openButton = new ClickableLabel;
-    QFont f(m_openButton->font());
-    f.setBold(true);
-    m_openButton->setFont(f);
-    m_openButton->setMouseUnderline(true);
-    connect(m_openButton, SIGNAL(clicked()), this, SLOT(openButtonClicked()));
-    layout->addWidget(m_openButton, row, 1, 1, 2, Qt::AlignLeft);
-
-    ++row;
-    layout->addWidget(new QLabel(tr("Remote:")), row, 0);
-    m_remoteURLLabel = new QLabel;
-    layout->addWidget(m_remoteURLLabel, row, 1, 1, 2);
-
-    ++row;
-    layout->addWidget(new QLabel(tr("State:")), row, 0);
-    m_stateLabel = new QLabel;
-    layout->addWidget(m_stateLabel, row, 1, 1, 2);
-
-    layout->setColumnStretch(1, 20);
-
-    layout->addWidget(new QLabel("<qt><hr></qt>"), ++row, 0, 1, 3);
-
-    ++row;
-
     m_noModificationsLabel = new QLabel;
     setNoModificationsLabelText();
-    layout->addWidget(m_noModificationsLabel, row, 1, 1, 2);
+    layout->addWidget(m_noModificationsLabel, row, 0);
     m_noModificationsLabel->hide();
 
     m_simpleLabels[FileStates::Clean] = tr("Unmodified:");
@@ -107,7 +75,7 @@
                                 "have appeared since your most recent commit or update.");
 
     m_boxesParent = new QWidget(this);
-    layout->addWidget(m_boxesParent, ++row, 0, 1, 3);
+    layout->addWidget(m_boxesParent, ++row, 0);
 
     QGridLayout *boxesLayout = new QGridLayout;
     boxesLayout->setMargin(0);
@@ -152,7 +120,7 @@
     layout->addItem(new QSpacerItem(8, 8), ++row, 0);
 
     m_showAllFiles = new QCheckBox(tr("Show all files"), this);
-    layout->addWidget(m_showAllFiles, ++row, 0, 1, 3, Qt::AlignLeft);
+    layout->addWidget(m_showAllFiles, ++row, 0, Qt::AlignLeft);
     connect(m_showAllFiles, SIGNAL(toggled(bool)),
             this, SIGNAL(showAllChanged(bool)));
 }
@@ -162,32 +130,6 @@
     delete m_dateReference;
 }
 
-void FileStatusWidget::openButtonClicked()
-{
-    QDir d(m_localPath);
-    if (d.exists()) {
-        QStringList args;
-        QString path = d.canonicalPath();
-#if defined Q_OS_WIN32
-        // Although the Win32 API is quite happy to have
-        // forward slashes as directory separators, Windows
-        // Explorer is not
-        path = path.replace('/', '\\');
-        args << path;
-        QProcess::execute("c:/windows/explorer.exe", args);
-#else
-        args << path;
-        QProcess::execute(
-#if defined Q_OS_MAC
-            "/usr/bin/open",
-#else
-            "/usr/bin/xdg-open",
-#endif
-            args);
-#endif
-    }
-}
-
 QString FileStatusWidget::labelFor(FileStates::State s, bool addHighlightExplanation)
 {
     QSettings settings;
@@ -412,11 +354,16 @@
     return files;
 }
 
+QString
+FileStatusWidget::localPath() const
+{
+    return m_localPath;
+}
+
 void
 FileStatusWidget::setLocalPath(QString p)
 {
     m_localPath = p;
-    m_openButton->setText(p);
     delete m_dateReference;
     m_dateReference = new QFileInfo(p + "/.hg/dirstate");
     if (!m_dateReference->exists() ||
@@ -429,14 +376,6 @@
         delete m_dateReference;
         m_dateReference = 0;
     }
-    m_openButton->setEnabled(QDir(m_localPath).exists());
-}
-
-void
-FileStatusWidget::setRemoteURL(QString r)
-{
-    m_remoteURL = r;
-    m_remoteURLLabel->setText(r);
 }
 
 void
@@ -447,13 +386,6 @@
 }
 
 void
-FileStatusWidget::setState(QString b)
-{
-    m_state = b;
-    updateStateLabel();
-}
-
-void
 FileStatusWidget::updateWidgets()
 {
     QDateTime lastInteractionTime;
@@ -530,7 +462,6 @@
         layoutBoxesLinearly();
     }
 
-    updateStateLabel();
     setNoModificationsLabelText();
 }
 
@@ -594,7 +525,3 @@
     if (!ql.empty()) ql[0]->setText(text);
 }
 
-void FileStatusWidget::updateStateLabel()
-{
-    m_stateLabel->setText(m_state);
-}
--- a/filestatuswidget.h	Mon Feb 28 17:35:55 2011 +0000
+++ b/filestatuswidget.h	Tue Mar 01 14:22:53 2011 +0000
@@ -27,7 +27,6 @@
 class QListWidget;
 class QPushButton;
 class QFileInfo;
-class ClickableLabel;
 class QCheckBox;
 
 class FileStatusWidget : public QWidget
@@ -38,16 +37,10 @@
     FileStatusWidget(QWidget *parent = 0);
     ~FileStatusWidget();
 
-    QString localPath() const { return m_localPath; }
+    QString localPath() const;
     void setLocalPath(QString p);
 
-    QString remoteURL() const { return m_remoteURL; }
-    void setRemoteURL(QString u);
-
-    QString state() const { return m_state; }
-    void setState(QString b);
-
-    FileStates fileStates() const { return m_fileStates; }
+    FileStates fileStates() const;
     void setFileStates(FileStates sp);
 
     bool haveChangesToCommit() const;
@@ -80,18 +73,9 @@
 
 private slots:
     void itemSelectionChanged();
-    void openButtonClicked();
 
 private:
     QString m_localPath;
-    ClickableLabel *m_openButton;
-
-    QString m_remoteURL;
-    QLabel *m_remoteURLLabel;
-
-    QString m_state;
-    QLabel *m_stateLabel;
-    
     QLabel *m_noModificationsLabel;
 
     QCheckBox *m_showAllFiles;
@@ -112,7 +96,6 @@
 
     void layoutBoxesGridly(int count);
     void layoutBoxesLinearly();
-    void updateStateLabel();
     void setNoModificationsLabelText();
     QString labelFor(FileStates::State, bool addHighlightExplanation = false);
     void setLabelFor(QWidget *w, FileStates::State, bool addHighlightExplanation);
--- a/grapher.cpp	Mon Feb 28 17:35:55 2011 +0000
+++ b/grapher.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -233,6 +233,7 @@
         }
     }
 
+
     // Normally the children will lay out themselves, but we can do
     // a better job in some special cases:
 
@@ -431,18 +432,32 @@
     // Add uncommitted item and connecting line as necessary
 
     if (!m_uncommittedParents.empty()) {
+
         m_uncommitted = new UncommittedItem();
         m_uncommitted->setBranch(uncommittedBranch);
         m_uncommitted->setZValue(10);
         m_scene->addUncommittedItem(m_uncommitted);
+
+        bool haveParentOnBranch = false;
         foreach (QString p, m_uncommittedParents) {
             ConnectionItem *conn = new ConnectionItem();
             conn->setConnectionType(ConnectionItem::Merge);
-            conn->setParent(m_items[p]);
+            ChangesetItem *pitem = m_items[p];
+            conn->setParent(pitem);
             conn->setChild(m_uncommitted);
             conn->setZValue(0);
             m_scene->addItem(conn);
+            if (pitem) {
+                if (pitem->getChangeset()->branch() == uncommittedBranch) {
+                    haveParentOnBranch = true;
+                }
+            }
         }
+
+        // If the uncommitted item has no parents on the same branch,
+        // tell it it has a new branch (the "show branch" flag is set
+        // elsewhere for this item)
+        m_uncommitted->setIsNewBranch(!haveParentOnBranch);
     }
 
     // Add the branch labels
--- a/hgaction.h	Mon Feb 28 17:35:55 2011 +0000
+++ b/hgaction.h	Tue Mar 01 14:22:53 2011 +0000
@@ -54,6 +54,7 @@
     ACT_RESOLVE_MARK,
     ACT_RETRY_MERGE,
     ACT_TAG,
+    ACT_NEW_BRANCH,
     ACT_HG_IGNORE,
 };
 
--- a/hgtabwidget.cpp	Mon Feb 28 17:35:55 2011 +0000
+++ b/hgtabwidget.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -27,14 +27,12 @@
 #include <iostream>
 
 HgTabWidget::HgTabWidget(QWidget *parent,
-                         QString remoteRepo,
                          QString workFolderPath) :
     QTabWidget(parent)
 {
     // Work page
     m_fileStatusWidget = new FileStatusWidget;
     m_fileStatusWidget->setLocalPath(workFolderPath);
-    m_fileStatusWidget->setRemoteURL(remoteRepo);
     connect(m_fileStatusWidget, SIGNAL(selectionChanged()),
             this, SIGNAL(selectionChanged()));
     connect(m_fileStatusWidget, SIGNAL(showAllChanged(bool)),
@@ -54,6 +52,12 @@
     connect(m_historyWidget, SIGNAL(showSummary()),
             this, SIGNAL(showSummary()));
     
+    connect(m_historyWidget, SIGNAL(newBranch()),
+            this, SIGNAL(newBranch()));
+    
+    connect(m_historyWidget, SIGNAL(noBranch()),
+            this, SIGNAL(noBranch()));
+    
     connect(m_historyWidget, SIGNAL(diffWorkingFolder()),
             this, SIGNAL(diffWorkingFolder()));
 
@@ -75,6 +79,9 @@
     connect(m_historyWidget, SIGNAL(mergeFrom(QString)),
             this, SIGNAL(mergeFrom(QString)));
 
+    connect(m_historyWidget, SIGNAL(newBranch(QString)),
+            this, SIGNAL(newBranch(QString)));
+
     connect(m_historyWidget, SIGNAL(tag(QString)),
             this, SIGNAL(tag(QString)));
 }
@@ -243,15 +250,9 @@
     }
 }
 
-void HgTabWidget::setWorkFolderAndRepoNames(QString workFolderPath, QString remoteRepoPath)
+void HgTabWidget::setLocalPath(QString workFolderPath)
 {
     m_fileStatusWidget->setLocalPath(workFolderPath);
-    m_fileStatusWidget->setRemoteURL(remoteRepoPath);
-}
-
-void HgTabWidget::setState(QString state)
-{
-    m_fileStatusWidget->setState(state);
 }
 
 void HgTabWidget::showWorkTab()
--- a/hgtabwidget.h	Mon Feb 28 17:35:55 2011 +0000
+++ b/hgtabwidget.h	Tue Mar 01 14:22:53 2011 +0000
@@ -38,15 +38,14 @@
     Q_OBJECT
 
 public:
-    HgTabWidget(QWidget *parent, QString remoteRepo, QString workFolderPath);
+    HgTabWidget(QWidget *parent, QString workFolderPath);
 
     void updateWorkFolderFileList(QString fileList);
 
     void setNewLog(QString hgLogList);
     void addIncrementalLog(QString hgLogList);
 
-    void setWorkFolderAndRepoNames(QString workFolderPath, QString remoteRepoPath);
-    void setState(QString state);
+    void setLocalPath(QString workFolderPath);
 
     void setCurrent(QStringList ids, QString branch);
 
@@ -88,12 +87,15 @@
     void revert();
     void diffWorkingFolder();
     void showSummary();
+    void newBranch();
+    void noBranch();
 
     void updateTo(QString id);
     void diffToParent(QString id, QString parent);
     void showSummary(Changeset *);
     void diffToCurrent(QString id);
     void mergeFrom(QString id);
+    void newBranch(QString id);
     void tag(QString id);
 
 public slots:
--- a/historywidget.cpp	Mon Feb 28 17:35:55 2011 +0000
+++ b/historywidget.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -268,6 +268,12 @@
 
     connect(scene, SIGNAL(showWork()),
             this, SIGNAL(showWork()));
+
+    connect(scene, SIGNAL(newBranch()),
+            this, SIGNAL(newBranch()));
+
+    connect(scene, SIGNAL(noBranch()),
+            this, SIGNAL(noBranch()));
     
     connect(scene, SIGNAL(updateTo(QString)),
             this, SIGNAL(updateTo(QString)));
@@ -284,6 +290,9 @@
     connect(scene, SIGNAL(mergeFrom(QString)),
             this, SIGNAL(mergeFrom(QString)));
 
+    connect(scene, SIGNAL(newBranch(QString)),
+            this, SIGNAL(newBranch(QString)));
+
     connect(scene, SIGNAL(tag(QString)),
             this, SIGNAL(tag(QString)));
 }
--- a/historywidget.h	Mon Feb 28 17:35:55 2011 +0000
+++ b/historywidget.h	Tue Mar 01 14:22:53 2011 +0000
@@ -51,12 +51,15 @@
     void diffWorkingFolder();
     void showSummary();
     void showWork();
+    void newBranch();
+    void noBranch();
 
     void updateTo(QString id);
     void diffToParent(QString id, QString parent);
     void showSummary(Changeset *);
     void diffToCurrent(QString id);
     void mergeFrom(QString id);
+    void newBranch(QString id);
     void tag(QString id);
     
 private:
--- a/mainwindow.cpp	Mon Feb 28 17:35:55 2011 +0000
+++ b/mainwindow.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -45,6 +45,7 @@
 #include "settingsdialog.h"
 #include "moreinformationdialog.h"
 #include "version.h"
+#include "workstatuswidget.h"
 
 
 MainWindow::MainWindow(QString myDirPath) :
@@ -89,20 +90,21 @@
     QWidget *central = new QWidget(this);
     setCentralWidget(central);
 
-    m_hgTabs = new HgTabWidget(central, m_remoteRepoPath, m_workFolderPath);
-    connectTabsSignals();
-
-    // Instead of setting the tab widget as our central widget
-    // directly, put it in a layout, so that we can have some space
-    // around it on the Mac where it looks very strange without
-
     QGridLayout *cl = new QGridLayout(central);
-    cl->addWidget(m_hgTabs, 0, 0);
+    int row = 0;
 
 #ifndef Q_OS_MAC
     cl->setMargin(0);
 #endif
 
+    m_workStatus = new WorkStatusWidget(this);
+    cl->addWidget(m_workStatus, row++, 0);
+
+    m_hgTabs = new HgTabWidget(central, m_workFolderPath);
+    connectTabsSignals();
+
+    cl->addWidget(m_hgTabs, row++, 0);
+
     connect(m_hgTabs, SIGNAL(selectionChanged()),
             this, SLOT(enableDisableActions()));
     connect(m_hgTabs, SIGNAL(showAllChanged(bool)),
@@ -261,7 +263,7 @@
     // We have to do this here, because commandCompleted won't be called
     MultiChoiceDialog::addRecentArgument("local", m_workFolderPath);
     MultiChoiceDialog::addRecentArgument("remote", m_remoteRepoPath);
-    m_hgTabs->setWorkFolderAndRepoNames(m_workFolderPath, m_remoteRepoPath);
+    updateWorkFolderAndRepoNames();
     
     hgQueryBranch();
     return;
@@ -427,14 +429,21 @@
     
     QString cf(tr("Commit files"));
 
+    QString branchText;
+    if (m_currentBranch == "" || m_currentBranch == "default") {
+        branchText = tr("the default branch");
+    } else {
+        branchText = tr("branch \"%1\"").arg(m_currentBranch);
+    }
+
     if (ConfirmCommentDialog::confirmAndGetLongComment
         (this,
          cf,
          tr("<h3>%1</h3><p>%2%3").arg(cf)
-         .arg(tr("You are about to commit the following files."))
+         .arg(tr("You are about to commit the following files to %1.").arg(branchText))
          .arg(subsetNote),
          tr("<h3>%1</h3><p>%2%3").arg(cf)
-         .arg(tr("You are about to commit %n file(s).", "", reportFiles.size()))
+         .arg(tr("You are about to commit %n file(s) to %1.", "", reportFiles.size()).arg(branchText))
          .arg(subsetNote),
          reportFiles,
          comment,
@@ -458,14 +467,11 @@
 
 QString MainWindow::filterTag(QString tag)
 {
-    for(int i = 0; i < tag.size(); i++)
-    {
-        if (tag[i].isLower() || tag[i].isUpper() || tag[i].isDigit() || (tag[i] == QChar('.')))
-        {
+    for(int i = 0; i < tag.size(); i++) {
+        if (tag[i].isLower() || tag[i].isUpper() ||
+            tag[i].isDigit() || (tag[i] == QChar('.'))) {
             //ok
-        }
-        else
-        {
+        } else {
             tag[i] = QChar('_');
         }
     }
@@ -473,6 +479,39 @@
 }
 
 
+void MainWindow::hgNewBranch()
+{
+    QStringList params;
+    QString branch;
+
+    if (ConfirmCommentDialog::confirmAndGetShortComment
+        (this,
+         tr("New Branch"),
+         tr("Enter new branch name:"),
+         branch,
+         tr("Start Branch"))) {
+        if (!branch.isEmpty()) {//!!! do something better if it is empty
+
+            params << "branch" << filterTag(branch);
+            m_runner->requestAction(HgAction(ACT_NEW_BRANCH, m_workFolderPath, params));
+        }
+    }
+}
+
+
+void MainWindow::hgNoBranch()
+{
+    if (m_currentParents.empty()) return;
+
+    QString parentBranch = m_currentParents[0]->branch();
+    if (parentBranch == "") parentBranch = "default";
+
+    QStringList params;
+    params << "branch" << parentBranch;
+    m_runner->requestAction(HgAction(ACT_NEW_BRANCH, m_workFolderPath, params));
+}
+
+
 void MainWindow::hgTag(QString id)
 {
     QStringList params;
@@ -840,7 +879,7 @@
 
     params << "clone" << m_remoteRepoPath << m_workFolderPath;
     
-    m_hgTabs->setWorkFolderAndRepoNames(m_workFolderPath, m_remoteRepoPath);
+    updateWorkFolderAndRepoNames();
     m_hgTabs->updateWorkFolderFileList("");
 
     m_runner->requestAction(HgAction(ACT_CLONEFROMREMOTE, m_workFolderPath, params));
@@ -1811,7 +1850,7 @@
         }
         MultiChoiceDialog::addRecentArgument("local", m_workFolderPath);
         MultiChoiceDialog::addRecentArgument("remote", m_remoteRepoPath);
-        m_hgTabs->setWorkFolderAndRepoNames(m_workFolderPath, m_remoteRepoPath);
+        updateWorkFolderAndRepoNames();
         break;
     }
 
@@ -1939,6 +1978,10 @@
         m_shouldHgStat = true;
         break;
 
+    case ACT_NEW_BRANCH:
+        m_shouldHgStat = true;
+        break;
+
     case ACT_UNCOMMITTED_SUMMARY:
         QMessageBox::information(this, tr("Change summary"),
                                  format3(tr("Summary of uncommitted changes"),
@@ -2142,6 +2185,12 @@
     
     connect(m_hgTabs, SIGNAL(showSummary()),
             this, SLOT(hgShowSummary()));
+    
+    connect(m_hgTabs, SIGNAL(newBranch()),
+            this, SLOT(hgNewBranch()));
+    
+    connect(m_hgTabs, SIGNAL(noBranch()),
+            this, SLOT(hgNoBranch()));
 
     connect(m_hgTabs, SIGNAL(updateTo(QString)),
             this, SLOT(hgUpdateToRev(QString)));
@@ -2158,6 +2207,9 @@
     connect(m_hgTabs, SIGNAL(mergeFrom(QString)),
             this, SLOT(hgMergeFrom(QString)));
 
+    connect(m_hgTabs, SIGNAL(newBranch(QString)),
+            this, SLOT(hgNewBranch()));
+
     connect(m_hgTabs, SIGNAL(tag(QString)),
             this, SLOT(hgTag(QString)));
 }    
@@ -2315,34 +2367,34 @@
 
     if (m_stateUnknown) {
         if (m_workFolderPath == "") {
-            m_hgTabs->setState(tr("No repository open"));
+            m_workStatus->setState(tr("No repository open"));
         } else {
-            m_hgTabs->setState(tr("(Examining repository)"));
+            m_workStatus->setState(tr("(Examining repository)"));
         }
     } else if (emptyRepo) {
-        m_hgTabs->setState(tr("Nothing committed to this repository yet"));
+        m_workStatus->setState(tr("Nothing committed to this repository yet"));
     } else if (noWorkingCopy) {
-        m_hgTabs->setState(tr("No working copy yet: consider updating"));
+        m_workStatus->setState(tr("No working copy yet: consider updating"));
     } else if (canMerge) {
-        m_hgTabs->setState(tr("<b>Awaiting merge</b> on %1").arg(branchText));
+        m_workStatus->setState(tr("<b>Awaiting merge</b> on %1").arg(branchText));
     } else if (!m_hgTabs->getAllUnresolvedFiles().empty()) {
-        m_hgTabs->setState(tr("Have unresolved files following merge on %1").arg(branchText));
+        m_workStatus->setState(tr("Have unresolved files following merge on %1").arg(branchText));
     } else if (haveMerge) {
-        m_hgTabs->setState(tr("Have merged but not yet committed on %1").arg(branchText));
+        m_workStatus->setState(tr("Have merged but not yet committed on %1").arg(branchText));
     } else if (newBranch) {
-        m_hgTabs->setState(tr("On %1.  New branch: has not yet been committed").arg(branchText));
+        m_workStatus->setState(tr("On %1.  New branch: has not yet been committed").arg(branchText));
     } else if (canUpdate) {
         if (m_hgTabs->haveChangesToCommit()) {
             // have uncommitted changes
-            m_hgTabs->setState(tr("On %1. Not at the head of the branch").arg(branchText));
+            m_workStatus->setState(tr("On %1. Not at the head of the branch").arg(branchText));
         } else {
             // no uncommitted changes
-            m_hgTabs->setState(tr("On %1. Not at the head of the branch: consider updating").arg(branchText));
+            m_workStatus->setState(tr("On %1. Not at the head of the branch: consider updating").arg(branchText));
         }
     } else if (m_currentBranchHeads > 1) {
-        m_hgTabs->setState(tr("At one of %n heads of %1", "", m_currentBranchHeads).arg(branchText));
+        m_workStatus->setState(tr("At one of %n heads of %1", "", m_currentBranchHeads).arg(branchText));
     } else {
-        m_hgTabs->setState(tr("At the head of %1").arg(branchText));
+        m_workStatus->setState(tr("At the head of %1").arg(branchText));
     }
 }
 
@@ -2489,14 +2541,19 @@
     }
 }    
 
+void MainWindow::updateWorkFolderAndRepoNames()
+{
+    m_hgTabs->setLocalPath(m_workFolderPath);
+
+    m_workStatus->setLocalPath(m_workFolderPath);
+    m_workStatus->setRemoteURL(m_remoteRepoPath);
+}
+
 void MainWindow::createStatusBar()
 {
     statusBar()->showMessage(tr("Ready"));
 }
 
-
-//!!! review these:
-
 void MainWindow::readSettings()
 {
     QDir workFolder;
@@ -2514,12 +2571,10 @@
     QSize size = settings.value("size", QSize(400, 400)).toSize();
     m_firstStart = settings.value("firststart", QVariant(true)).toBool();
 
-//!!!    initialFileTypesBits = (unsigned char) settings.value("viewFileTypes", QVariant(DEFAULT_HG_STAT_BITS)).toInt();
     resize(size);
     move(pos);
 }
 
-
 void MainWindow::writeSettings()
 {
     QSettings settings;
@@ -2528,7 +2583,6 @@
     settings.setValue("remoterepopath", m_remoteRepoPath);
     settings.setValue("workfolderpath", m_workFolderPath);
     settings.setValue("firststart", m_firstStart);
-    //!!!settings.setValue("viewFileTypes", m_hgTabs -> getFileTypesBits());
 }
 
 
--- a/mainwindow.h	Mon Feb 28 17:35:55 2011 +0000
+++ b/mainwindow.h	Tue Mar 01 14:22:53 2011 +0000
@@ -34,6 +34,8 @@
 class QTimer;
 QT_END_NAMESPACE
 
+class WorkStatusWidget;
+
 class MainWindow : public QMainWindow
 {
     Q_OBJECT
@@ -88,6 +90,8 @@
     void hgAnnotate();
     void hgResolveList();
     void hgTag(QString);
+    void hgNewBranch();
+    void hgNoBranch();
     void hgServe();
     void hgIgnore();
 
@@ -151,6 +155,9 @@
     void suspendFileSystemWatcher();
     void restoreFileSystemWatcher();
 
+    void updateWorkFolderAndRepoNames();
+
+    WorkStatusWidget *m_workStatus;
     HgTabWidget *m_hgTabs;
 
     QString m_remoteRepoPath;
--- a/uncommitteditem.cpp	Mon Feb 28 17:35:55 2011 +0000
+++ b/uncommitteditem.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -29,7 +29,8 @@
 #include <QWidgetAction>
 
 UncommittedItem::UncommittedItem() :
-    m_showBranch(false), m_column(0), m_row(0), m_wide(false)
+    m_showBranch(false), m_isNewBranch(false),
+    m_column(0), m_row(0), m_wide(false)
 {
     m_font = QFont();
     m_font.setPixelSize(11);
@@ -87,6 +88,14 @@
     QAction *revert = menu->addAction(tr("Revert..."));
     connect(revert, SIGNAL(triggered()), this, SIGNAL(revert()));
 
+    menu->addSeparator();
+
+    QAction *branch = menu->addAction(tr("Start new branch..."));
+    connect(branch, SIGNAL(triggered()), this, SIGNAL(newBranch()));
+    QAction *nobranch = menu->addAction(tr("Cancel new branch"));
+    nobranch->setEnabled(m_isNewBranch);
+    connect(nobranch, SIGNAL(triggered()), this, SIGNAL(noBranch()));
+
     menu->exec(QCursor::pos());
 
     ungrabMouse();
--- a/uncommitteditem.h	Mon Feb 28 17:35:55 2011 +0000
+++ b/uncommitteditem.h	Tue Mar 01 14:22:53 2011 +0000
@@ -36,6 +36,9 @@
 
     bool showBranch() const { return m_showBranch; }
     void setShowBranch(bool s) { m_showBranch = s; }
+
+    bool isNewBranch() const { return m_isNewBranch; }
+    void setIsNewBranch(bool s) { m_isNewBranch = s; }
     
     int column() const { return m_column; }
     int row() const { return m_row; }
@@ -51,6 +54,8 @@
     void diff();
     void showSummary();
     void showWork();
+    void newBranch();
+    void noBranch();
 
 protected:
     virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
@@ -61,6 +66,7 @@
 
     QString m_branch;
     bool m_showBranch;
+    bool m_isNewBranch;
     QFont m_font;
     int m_column;
     int m_row;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/workstatuswidget.cpp	Tue Mar 01 14:22:53 2011 +0000
@@ -0,0 +1,125 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    EasyMercurial
+
+    Based on HgExplorer by Jari Korhonen
+    Copyright (c) 2010 Jari Korhonen
+    Copyright (c) 2011 Chris Cannam
+    Copyright (c) 2011 Queen Mary, University of London
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "workstatuswidget.h"
+#include "debug.h"
+#include "clickablelabel.h"
+
+#include <QGridLayout>
+#include <QSpacerItem>
+#include <QLabel>
+#include <QProcess>
+#include <QDir>
+
+WorkStatusWidget::WorkStatusWidget(QWidget *parent) :
+    QWidget(parent)
+{
+    QGridLayout *layout = new QGridLayout;
+    layout->setMargin(6);
+    layout->setSpacing(6);
+    setLayout(layout);
+
+    int row = 0;
+
+#ifndef Q_OS_MAC    
+    layout->addItem(new QSpacerItem(1, 1), row, 0);
+    ++row;
+#endif
+
+    layout->addWidget(new QLabel(tr("Local:")), row, 1);
+
+    m_openButton = new ClickableLabel;
+    QFont f(m_openButton->font());
+    f.setBold(true);
+    m_openButton->setFont(f);
+    m_openButton->setMouseUnderline(true);
+    connect(m_openButton, SIGNAL(clicked()), this, SLOT(openButtonClicked()));
+    layout->addWidget(m_openButton, row, 2, 1, 2, Qt::AlignLeft);
+
+    ++row;
+    layout->addWidget(new QLabel(tr("Remote:")), row, 1);
+    m_remoteURLLabel = new QLabel;
+    layout->addWidget(m_remoteURLLabel, row, 2, 1, 2);
+
+    ++row;
+    layout->addWidget(new QLabel(tr("State:")), row, 1);
+    m_stateLabel = new QLabel;
+    layout->addWidget(m_stateLabel, row, 2, 1, 2);
+
+    layout->setColumnStretch(2, 20);
+
+
+}
+
+WorkStatusWidget::~WorkStatusWidget()
+{
+}
+
+void
+WorkStatusWidget::setLocalPath(QString p)
+{
+    m_localPath = p;
+    m_openButton->setText(p);
+    m_openButton->setEnabled(QDir(m_localPath).exists());
+}
+
+void
+WorkStatusWidget::setRemoteURL(QString r)
+{
+    m_remoteURL = r;
+    m_remoteURLLabel->setText(r);
+}
+
+void
+WorkStatusWidget::setState(QString b)
+{
+    m_state = b;
+    updateStateLabel();
+}
+
+void
+WorkStatusWidget::updateStateLabel()
+{
+    m_stateLabel->setText(m_state);
+}
+
+void
+WorkStatusWidget::openButtonClicked()
+{
+    QDir d(m_localPath);
+    if (d.exists()) {
+        QStringList args;
+        QString path = d.canonicalPath();
+#if defined Q_OS_WIN32
+        // Although the Win32 API is quite happy to have
+        // forward slashes as directory separators, Windows
+        // Explorer is not
+        path = path.replace('/', '\\');
+        args << path;
+        QProcess::execute("c:/windows/explorer.exe", args);
+#else
+        args << path;
+        QProcess::execute(
+#if defined Q_OS_MAC
+            "/usr/bin/open",
+#else
+            "/usr/bin/xdg-open",
+#endif
+            args);
+#endif
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/workstatuswidget.h	Tue Mar 01 14:22:53 2011 +0000
@@ -0,0 +1,62 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    EasyMercurial
+
+    Based on HgExplorer by Jari Korhonen
+    Copyright (c) 2010 Jari Korhonen
+    Copyright (c) 2011 Chris Cannam
+    Copyright (c) 2011 Queen Mary, University of London
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef WORKSTATUSWIDGET_H
+#define WORKSTATUSWIDGET_H
+
+#include <QWidget>
+
+class QLabel;
+class QPushButton;
+class QFileInfo;
+class ClickableLabel;
+class QCheckBox;
+
+class WorkStatusWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    WorkStatusWidget(QWidget *parent = 0);
+    ~WorkStatusWidget();
+
+    QString localPath() const { return m_localPath; }
+    void setLocalPath(QString p);
+
+    QString remoteURL() const { return m_remoteURL; }
+    void setRemoteURL(QString u);
+
+    QString state() const { return m_state; }
+    void setState(QString b);
+
+private slots:
+    void openButtonClicked();
+
+private:
+    QString m_localPath;
+    ClickableLabel *m_openButton;
+
+    QString m_remoteURL;
+    QLabel *m_remoteURLLabel;
+
+    QString m_state;
+    QLabel *m_stateLabel;
+
+    void updateStateLabel();
+};
+
+#endif