changeset 336:4229b6a8e9c6

Merge
author Chris Cannam
date Mon, 14 Mar 2011 10:00:29 +0000
parents aa852b477e4d (current diff) cee2e8691eeb (diff)
children a5813b625c6e
files easyhg.pro
diffstat 15 files changed, 567 insertions(+), 312 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/annotatedialog.cpp	Mon Mar 14 10:00:29 2011 +0000
@@ -0,0 +1,94 @@
+/* -*- 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 "annotatedialog.h"
+#include "common.h"
+#include "colourset.h"
+#include "debug.h"
+
+#include <QDialogButtonBox>
+#include <QLabel>
+#include <QTableWidget>
+#include <QHeaderView>
+#include <QGridLayout>
+
+AnnotateDialog::AnnotateDialog(QWidget *w, QString text) :
+    QDialog(w)
+{
+    setMinimumWidth(800);
+    setMinimumHeight(500);
+
+    text.replace("\r\n", "\n");
+    QStringList lines = text.split("\n");
+
+    QGridLayout *layout = new QGridLayout;
+    QTableWidget *table = new QTableWidget;
+
+    QRegExp annotateLineRE = QRegExp("^([^:]+) ([a-z0-9]{12}) ([0-9-]+): (.*)$");
+
+    table->setRowCount(lines.size());
+    table->setColumnCount(4);
+    table->horizontalHeader()->setStretchLastSection(true);
+    table->verticalHeader()->setDefaultSectionSize
+	(table->verticalHeader()->fontMetrics().height() + 2);
+
+    QStringList labels;
+    labels << tr("User") << tr("Revision") << tr("Date") << tr("Content");
+    table->setHorizontalHeaderLabels(labels);
+
+    table->setShowGrid(false);
+
+    QFont monofont("Monospace");
+    monofont.setStyleHint(QFont::TypeWriter);
+
+    int row = 0;
+
+    foreach (QString line, lines) {
+	if (annotateLineRE.indexIn(line) == 0) {
+	    QStringList items = annotateLineRE.capturedTexts();
+	    QString id = items[2];
+	    QColor colour = ColourSet::instance()->getColourFor(id);
+	    QColor bg = QColor::fromHsv(colour.hue(),
+					30,
+					230);
+	    // note items[0] is the whole match, so we want 1-4
+	    for (int col = 0; col+1 < items.size(); ++col) {
+		QString item = items[col+1];
+		if (col == 0) item = item.trimmed();
+		QTableWidgetItem *wi = new QTableWidgetItem(item);
+		wi->setFlags(Qt::ItemIsEnabled);
+		wi->setBackground(bg);
+		if (col == 3) { // id, content
+		    wi->setFont(monofont);
+		}
+		table->setItem(row, col, wi);
+	    }
+	} else {
+	    DEBUG << "AnnotateDialog: Failed to match RE in line: " << line << " at row " << row << endl;
+	}
+	++row;
+    }
+
+    QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok);
+    connect(bb, SIGNAL(accepted()), this, SLOT(accept()));
+
+    layout->addWidget(table, 0, 0);
+    layout->addWidget(bb, 1, 0);
+
+    setLayout(layout);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/annotatedialog.h	Mon Mar 14 10:00:29 2011 +0000
@@ -0,0 +1,31 @@
+/* -*- 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 ANNOTATE_DIALOG_H
+#define ANNOTATE_DIALOG_H
+
+#include <QDialog>
+
+class AnnotateDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    AnnotateDialog(QWidget *parent, QString output);
+};
+
+#endif
--- a/easyhg-extdiff.sh	Wed Mar 02 15:58:34 2011 +0000
+++ b/easyhg-extdiff.sh	Mon Mar 14 10:00:29 2011 +0000
@@ -7,24 +7,17 @@
 while [ $# -gt 2 ]; do
     shift
 done
-found=""
 for d in kdiff3 kdiff3.exe; do
     if [ -x "$p/$d" ]; then
-	found=true
-	"$p/$d" "$1" "$2"
-	break
+	exec "$p/$d" "$1" "$2"
     elif [ -x "$(type -path $d)" ]; then
-	found=true
-	"$d" "$1" "$2"
-	break;
+	exec "$d" "$1" "$2"
     fi
 done
-if [ -z "$found" ]; then
-    od=/usr/bin/opendiff
-    if [ -x "$od" ]; then
-	found=true
-	"$od" "$1" "$2" | cat
-    fi
+od=/usr/bin/opendiff
+if [ -x "$od" ]; then
+    "$od" "$1" "$2" | cat
+    exit 0
 fi
-[ -n "$found" ]
+exit 1
 
--- a/easyhg-merge.sh	Wed Mar 02 15:58:34 2011 +0000
+++ b/easyhg-merge.sh	Mon Mar 14 10:00:29 2011 +0000
@@ -12,23 +12,15 @@
 left="$1"
 ancestor="$2"
 right="$3"
-found=""
 for d in kdiff3 kdiff3.exe; do
     if [ -x "$p/$d" ]; then
-	found=true
-	"$p/$d" "$ancestor" "$left" "$right" -o "$out"
-	break
+	exec "$p/$d" "$ancestor" "$left" "$right" -o "$out"
     elif [ -x "$(type -path $d)" ]; then
-	found=true
-	"$d" "$ancestor" "$left" "$right" -o "$out"
-	break;
+	exec "$d" "$ancestor" "$left" "$right" -o "$out"
     fi
 done
-if [ -z "$found" ]; then
-    fm=/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge
-    if [ -x "$fm" ]; then
-	found=true
-	"$fm" -left "$left" -merge "$out" -ancestor "$ancestor" -right "$right"
-    fi
+fm=/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge
+if [ -x "$fm" ]; then
+    exec "$fm" -left "$left" -merge "$out" -ancestor "$ancestor" -right "$right"
 fi
-[ -n "$found" ]
+exit 1
--- a/easyhg.pro	Wed Mar 02 15:58:34 2011 +0000
+++ b/easyhg.pro	Mon Mar 14 10:00:29 2011 +0000
@@ -59,7 +59,8 @@
     settingsdialog.h \
     clickablelabel.h \
     workstatuswidget.h \
-    moreinformationdialog.h
+    moreinformationdialog.h \
+    annotatedialog.h
 SOURCES = main.cpp \
     mainwindow.cpp \
     hgtabwidget.cpp \
@@ -91,7 +92,8 @@
     uncommitteditem.cpp \
     settingsdialog.cpp \
     workstatuswidget.cpp \
-    moreinformationdialog.cpp
+    moreinformationdialog.cpp \
+    annotatedialog.cpp
 
 macx-* {
     SOURCES += common_osx.mm
--- a/filestates.cpp	Wed Mar 02 15:58:34 2011 +0000
+++ b/filestates.cpp	Mon Mar 14 10:00:29 2011 +0000
@@ -63,7 +63,7 @@
 QStringList *FileStates::stateToBucket(State s)
 {
     switch (s) {
-    case Clean: return &m_clean; // not implemented yet
+    case Clean: return &m_clean;
     case Modified: return &m_modified;
     case Added: return &m_added;
     case Unknown: return &m_unknown;
@@ -112,14 +112,19 @@
           << m_unknown.size() << " unknown" << endl;
 }
 
-QStringList FileStates::getFilesInState(State s) const
+QStringList FileStates::filesInState(State s) const
 {
     QStringList *sl = const_cast<FileStates *>(this)->stateToBucket(s);
     if (sl) return *sl;
     else return QStringList();
 }
 
-FileStates::State FileStates::getStateOfFile(QString file) const
+bool FileStates::isInState(QString file, State s) const
+{
+    return filesInState(s).contains(file);
+}
+
+FileStates::State FileStates::stateOf(QString file) const
 {
     if (m_stateMap.contains(file)) {
         return m_stateMap[file];
@@ -131,3 +136,85 @@
             << endl;
     return Unknown;
 }
+
+FileStates::Activities FileStates::activitiesSupportedBy(State s)
+{
+    Activities a;
+
+    switch (s) {
+
+    case Modified:
+        a << Annotate << Diff << Commit << Revert << Remove;
+        break;
+
+    case Added:
+        a << Commit << Revert << Remove;
+        break;
+        
+    case Removed:
+        a << Commit << Revert << Add;
+        break;
+
+    case InConflict:
+        a << Annotate << Diff << RedoMerge << MarkResolved << Revert;
+        break;
+
+    case Missing:
+        a << Revert << Remove;
+        break;
+        
+    case Unknown:
+        a << Add << Ignore;
+        break;
+
+    case Clean:
+        a << Annotate << Remove;
+        break;
+
+    case Ignored:
+        a << UnIgnore;
+        break;
+    }
+
+    return a;
+}
+
+bool FileStates::supportsActivity(State s, Activity a)
+{
+    return activitiesSupportedBy(s).contains(a);
+}
+
+int FileStates::activityGroup(Activity a)
+{
+    switch (a) {
+    case Annotate: case Diff: return 0;
+    case Commit: case Revert: return 1;
+    case Add: case Remove: return 2;
+    case RedoMerge: case MarkResolved: return 3;
+    case Ignore: case UnIgnore: return 4;
+    }
+    return 0;
+}
+
+bool FileStates::supportsActivity(QString file, Activity a) const
+{
+    return supportsActivity(stateOf(file), a);
+}
+
+QStringList FileStates::filesSupportingActivity(Activity a) const
+{
+    QStringList f;
+    for (int i = int(FirstState); i <= int(LastState); ++i) {
+        State s = (State)i;
+        if (supportsActivity(s, a)) {
+            f << filesInState(s);
+        }
+    }
+    return f;
+}
+
+FileStates::Activities FileStates::activitiesSupportedBy(QString file) const
+{
+    return activitiesSupportedBy(stateOf(file));
+}
+
--- a/filestates.h	Wed Mar 02 15:58:34 2011 +0000
+++ b/filestates.h	Mon Mar 14 10:00:29 2011 +0000
@@ -47,10 +47,11 @@
 
     void parseStates(QString text);
 
-    void clearBuckets();
+    bool isInState(QString file, State s) const;
+    QStringList filesInState(State s) const;
+    State stateOf(QString file) const;
 
-    QStringList getFilesInState(State) const;
-
+/*!!! -- to remove: */
     QStringList modified() const { return m_modified; }
     QStringList added() const { return m_added; }
     QStringList unknown() const { return m_unknown; }
@@ -60,7 +61,39 @@
     QStringList clean() const { return m_clean; }
     QStringList ignored() const { return m_ignored; }
 
-    State getStateOfFile(QString file) const;
+    enum Activity {
+
+        // These are in the order in which they want to be listed in
+        // the context menu
+
+        Diff,
+        Annotate,
+
+        Commit,
+        Revert,
+
+        Add,
+        Remove,
+
+        RedoMerge,
+        MarkResolved,
+
+        Ignore,
+        UnIgnore,
+
+        FirstActivity = Diff,
+        LastActivity = UnIgnore
+    };
+
+    typedef QList<Activity> Activities;
+
+    static bool supportsActivity(State s, Activity a);
+    static Activities activitiesSupportedBy(State s);
+    static int activityGroup(Activity a);
+    
+    bool supportsActivity(QString file, Activity a) const;
+    QStringList filesSupportingActivity(Activity) const;
+    Activities activitiesSupportedBy(QString file) const;
 
 private:
     QStringList m_modified;
@@ -73,6 +106,8 @@
     QStringList m_ignored;
     QMap<QString, State> m_stateMap;
 
+    void clearBuckets();
+
     State charToState(QChar, bool * = 0);
     QStringList *stateToBucket(State);
 };
--- a/filestatuswidget.cpp	Wed Mar 02 15:58:34 2011 +0000
+++ b/filestatuswidget.cpp	Mon Mar 14 10:00:29 2011 +0000
@@ -31,6 +31,7 @@
 #include <QProcess>
 #include <QCheckBox>
 #include <QSettings>
+#include <QAction>
 
 FileStatusWidget::FileStatusWidget(QWidget *parent) :
     QWidget(parent),
@@ -56,6 +57,17 @@
     m_simpleLabels[FileStates::Unknown] = tr("Untracked:");
     m_simpleLabels[FileStates::Ignored] = tr("Ignored:");
 
+    m_actionLabels[FileStates::Annotate] = tr("Show annotated version");
+    m_actionLabels[FileStates::Diff] = tr("Diff to parent");
+    m_actionLabels[FileStates::Commit] = tr("Commit...");
+    m_actionLabels[FileStates::Revert] = tr("Revert to last committed state");
+    m_actionLabels[FileStates::Add] = tr("Add to version control");
+    m_actionLabels[FileStates::Remove] = tr("Remove from version control");
+    m_actionLabels[FileStates::RedoMerge] = tr("Redo merge");
+    m_actionLabels[FileStates::MarkResolved] = tr("Mark conflict as resolved");
+    m_actionLabels[FileStates::Ignore] = tr("Ignore");
+    m_actionLabels[FileStates::UnIgnore] = tr("Stop ignoring");
+
     m_descriptions[FileStates::Clean] = tr("You have not changed these files.");
     m_descriptions[FileStates::Modified] = tr("You have changed these files since you last committed them.");
     m_descriptions[FileStates::Added] = tr("These files will be added to version control next time you commit them.");
@@ -105,6 +117,31 @@
 
         connect(w, SIGNAL(itemSelectionChanged()),
                 this, SLOT(itemSelectionChanged()));
+        connect(w, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
+                this, SLOT(itemDoubleClicked(QListWidgetItem *)));
+
+        FileStates::Activities activities = m_fileStates.activitiesSupportedBy(s);
+        int prevGroup = -1;
+        foreach (FileStates::Activity a, activities) {
+            // Skip activities which are not yet implemented
+            if (a == FileStates::Ignore ||
+                a == FileStates::UnIgnore) {
+                continue;
+            }
+            int group = FileStates::activityGroup(a);
+            if (group != prevGroup && prevGroup != -1) {
+                QAction *sep = new QAction("", w);
+                sep->setSeparator(true);
+                w->insertAction(0, sep);
+            }
+            prevGroup = group;
+            QAction *act = new QAction(m_actionLabels[a], w);
+            act->setProperty("state", s);
+            act->setProperty("activity", a);
+            connect(act, SIGNAL(triggered()), this, SLOT(menuActionActivated()));
+            w->insertAction(0, act);
+        }
+        w->setContextMenuPolicy(Qt::ActionsContextMenu);
 
         boxlayout->addItem(new QSpacerItem(2, 2), 3, 0);
 
@@ -173,6 +210,50 @@
     }
 }
 
+
+void FileStatusWidget::menuActionActivated()
+{
+    QAction *act = qobject_cast<QAction *>(sender());
+    if (!act) return;
+    
+    FileStates::State state = (FileStates::State)
+        act->property("state").toUInt();
+    FileStates::Activity activity = (FileStates::Activity)
+        act->property("activity").toUInt();
+
+    DEBUG << "menuActionActivated: state = " << state << ", activity = "
+          << activity << endl;
+
+    if (!FileStates::supportsActivity(state, activity)) {
+        std::cerr << "WARNING: FileStatusWidget::menuActionActivated: "
+                  << "Action state " << state << " does not support activity "
+                  << activity << std::endl;
+        return;
+    }
+
+    QStringList files = getSelectedFilesInState(state);
+
+    switch (activity) {
+    case FileStates::Annotate: emit annotateFiles(files); break;
+    case FileStates::Diff: emit diffFiles(files); break;
+    case FileStates::Commit: emit commitFiles(files); break;
+    case FileStates::Revert: emit revertFiles(files); break;
+    case FileStates::Add: emit addFiles(files); break;
+    case FileStates::Remove: emit removeFiles(files); break;
+    case FileStates::RedoMerge: emit redoFileMerges(files); break;
+    case FileStates::MarkResolved: emit markFilesResolved(files); break;
+    case FileStates::Ignore: emit ignoreFiles(files); break;
+    case FileStates::UnIgnore: emit unIgnoreFiles(files); break;
+    }
+}
+
+void FileStatusWidget::itemDoubleClicked(QListWidgetItem *item)
+{
+    QStringList files;
+    files << item->text();
+    emit annotateFiles(files);
+}
+
 void FileStatusWidget::itemSelectionChanged()
 {
     DEBUG << "FileStatusWidget::itemSelectionChanged" << endl;
@@ -212,9 +293,7 @@
 
 bool FileStatusWidget::haveChangesToCommit() const
 {
-    return !m_fileStates.added().empty() ||
-           !m_fileStates.removed().empty() ||
-           !m_fileStates.modified().empty();
+    return !getAllCommittableFiles().empty();
 }
 
 bool FileStatusWidget::haveSelection() const
@@ -222,136 +301,47 @@
     return !m_selectedFiles.empty();
 }
 
-QStringList FileStatusWidget::getAllSelectedFiles() const
-{
-    return m_selectedFiles;
-}
-
-QStringList FileStatusWidget::getSelectedCommittableFiles() const
+QStringList FileStatusWidget::getSelectedFilesInState(FileStates::State s) const
 {
     QStringList files;
     foreach (QString f, m_selectedFiles) {
-        switch (m_fileStates.getStateOfFile(f)) {
-        case FileStates::Added:
-        case FileStates::Modified:
-        case FileStates::Removed:
-            files.push_back(f);
-            break;
-        default: break;
-        }
+        if (m_fileStates.stateOf(f) == s) files.push_back(f);
     }
     return files;
-}
+}    
+
+QStringList FileStatusWidget::getSelectedFilesSupportingActivity(FileStates::Activity a) const
+{
+    QStringList files;
+    foreach (QString f, m_selectedFiles) {
+        if (m_fileStates.supportsActivity(f, a)) files.push_back(f);
+    }
+    return files;
+}    
 
 QStringList FileStatusWidget::getAllCommittableFiles() const
 {
-    QStringList files;
-    files << m_fileStates.getFilesInState(FileStates::Modified);
-    files << m_fileStates.getFilesInState(FileStates::Added);
-    files << m_fileStates.getFilesInState(FileStates::Removed);
-    return files;
-}
-
-QStringList FileStatusWidget::getSelectedRevertableFiles() const
-{
-    QStringList files;
-    foreach (QString f, m_selectedFiles) {
-        switch (m_fileStates.getStateOfFile(f)) {
-        case FileStates::Added:
-        case FileStates::Modified:
-        case FileStates::Removed:
-        case FileStates::Missing:
-        case FileStates::InConflict:
-            files.push_back(f);
-            break;
-        default: break;
-        }
-    }
-    return files;
+    return m_fileStates.filesSupportingActivity(FileStates::Commit);
 }
 
 QStringList FileStatusWidget::getAllRevertableFiles() const
 {
-    QStringList files;
-    files << m_fileStates.getFilesInState(FileStates::Modified);
-    files << m_fileStates.getFilesInState(FileStates::Added);
-    files << m_fileStates.getFilesInState(FileStates::Removed);
-    files << m_fileStates.getFilesInState(FileStates::Missing);
-    files << m_fileStates.getFilesInState(FileStates::InConflict);
-    return files;
-}
-
-QStringList FileStatusWidget::getSelectedUnresolvedFiles() const
-{
-    QStringList files;
-    foreach (QString f, m_selectedFiles) {
-        switch (m_fileStates.getStateOfFile(f)) {
-        case FileStates::InConflict:
-            files.push_back(f);
-            break;
-        default: break;
-        }
-    }
-    return files;
+    return m_fileStates.filesSupportingActivity(FileStates::Revert);
 }
 
 QStringList FileStatusWidget::getAllUnresolvedFiles() const
 {
-    QStringList files;
-    files << m_fileStates.getFilesInState(FileStates::InConflict);
-    return files;
+    return m_fileStates.filesInState(FileStates::InConflict);
 }
 
 QStringList FileStatusWidget::getSelectedAddableFiles() const
 {
-    QStringList files;
-    foreach (QString f, m_selectedFiles) {
-        switch (m_fileStates.getStateOfFile(f)) {
-        case FileStates::Unknown:
-        case FileStates::Removed:
-            files.push_back(f);
-            break;
-        default: break;
-        }
-    }
-    return files;
-}
-
-QStringList FileStatusWidget::getAllAddableFiles() const
-{
-    QStringList files;
-    files << m_fileStates.getFilesInState(FileStates::Removed);
-    files << m_fileStates.getFilesInState(FileStates::Unknown);
-    return files;
+    return getSelectedFilesSupportingActivity(FileStates::Add);
 }
 
 QStringList FileStatusWidget::getSelectedRemovableFiles() const
 {
-    QStringList files;
-    foreach (QString f, m_selectedFiles) {
-        switch (m_fileStates.getStateOfFile(f)) {
-        case FileStates::Clean:
-        case FileStates::Added:
-        case FileStates::Modified:
-        case FileStates::Missing:
-        case FileStates::InConflict:
-            files.push_back(f);
-            break;
-        default: break;
-        }
-    }
-    return files;
-}
-
-QStringList FileStatusWidget::getAllRemovableFiles() const
-{
-    QStringList files;
-    files << m_fileStates.getFilesInState(FileStates::Clean);
-    files << m_fileStates.getFilesInState(FileStates::Added);
-    files << m_fileStates.getFilesInState(FileStates::Modified);
-    files << m_fileStates.getFilesInState(FileStates::Missing);
-    files << m_fileStates.getFilesInState(FileStates::InConflict);
-    return files;
+    return getSelectedFilesSupportingActivity(FileStates::Remove);
 }
 
 QString
@@ -403,7 +393,7 @@
 
         QListWidget *w = m_stateListMap[s];
         w->clear();
-        QStringList files = m_fileStates.getFilesInState(s);
+        QStringList files = m_fileStates.filesInState(s);
 
         QStringList highPriority, lowPriority;
 
@@ -434,7 +424,7 @@
         foreach (QString file, highPriority) {
             QListWidgetItem *item = new QListWidgetItem(file);
             w->addItem(item);
-            item->setForeground(QColor("#d40000")); //!!! and a nice gold star
+            item->setForeground(QColor("#d40000"));
             item->setSelected(selectedFiles.contains(file));
         }
 
--- a/filestatuswidget.h	Wed Mar 02 15:58:34 2011 +0000
+++ b/filestatuswidget.h	Mon Mar 14 10:00:29 2011 +0000
@@ -25,6 +25,7 @@
 
 class QLabel;
 class QListWidget;
+class QListWidgetItem;
 class QPushButton;
 class QFileInfo;
 class QCheckBox;
@@ -46,33 +47,36 @@
     bool haveChangesToCommit() const;
     bool haveSelection() const;
 
-    QStringList getAllSelectedFiles() const;
-
-    QStringList getSelectedCommittableFiles() const;
     QStringList getAllCommittableFiles() const;
-
-    QStringList getSelectedRevertableFiles() const;
     QStringList getAllRevertableFiles() const;
+    QStringList getAllUnresolvedFiles() const;
 
     QStringList getSelectedAddableFiles() const;
-    QStringList getAllAddableFiles() const;
+    QStringList getSelectedRemovableFiles() const;
 
-    QStringList getSelectedRemovableFiles() const;
-    QStringList getAllRemovableFiles() const;
-
-    QStringList getSelectedUnresolvedFiles() const;
-    QStringList getAllUnresolvedFiles() const;
-    
 signals:
     void selectionChanged();
     void showAllChanged(bool);
 
+    void annotateFiles(QStringList);
+    void diffFiles(QStringList);
+    void commitFiles(QStringList);
+    void revertFiles(QStringList);
+    void addFiles(QStringList);
+    void removeFiles(QStringList);
+    void redoFileMerges(QStringList);
+    void markFilesResolved(QStringList);
+    void ignoreFiles(QStringList);
+    void unIgnoreFiles(QStringList);
+
 public slots:
     void clearSelections();
     void updateWidgets();
 
 private slots:
+    void menuActionActivated();
     void itemSelectionChanged();
+    void itemDoubleClicked(QListWidgetItem *);
 
 private:
     QString m_localPath;
@@ -84,6 +88,7 @@
     QMap<FileStates::State, QString> m_simpleLabels;
     QMap<FileStates::State, QString> m_descriptions;
     QMap<FileStates::State, QListWidget *> m_stateListMap;
+    QMap<FileStates::Activity, QString> m_actionLabels;
     QString m_highlightExplanation;
 
     QFileInfo *m_dateReference;
@@ -99,6 +104,9 @@
     void setNoModificationsLabelText();
     QString labelFor(FileStates::State, bool addHighlightExplanation = false);
     void setLabelFor(QWidget *w, FileStates::State, bool addHighlightExplanation);
+
+    QStringList getSelectedFilesInState(FileStates::State s) const;
+    QStringList getSelectedFilesSupportingActivity(FileStates::Activity) const;
 };
 
 #endif
--- a/hgrunner.cpp	Wed Mar 02 15:58:34 2011 +0000
+++ b/hgrunner.cpp	Mon Mar 14 10:00:29 2011 +0000
@@ -423,9 +423,7 @@
 #endif
 
 #ifdef Q_OS_MAC
-    // On OS/X 10.6, Python is 64-bit by default but our Hg extension
-    // is only available in 32-bit
-    if (settings.value("python32", true).toBool()) {
+    if (settings.value("python32", false).toBool()) {
         env.insert("VERSIONER_PYTHON_PREFER_32_BIT", "1");
     }
 #endif
--- a/hgtabwidget.cpp	Wed Mar 02 15:58:34 2011 +0000
+++ b/hgtabwidget.cpp	Mon Mar 14 10:00:29 2011 +0000
@@ -30,16 +30,49 @@
                          QString workFolderPath) :
     QTabWidget(parent)
 {
-    // Work page
+    // Work tab
     m_fileStatusWidget = new FileStatusWidget;
     m_fileStatusWidget->setLocalPath(workFolderPath);
+
     connect(m_fileStatusWidget, SIGNAL(selectionChanged()),
             this, SIGNAL(selectionChanged()));
+
     connect(m_fileStatusWidget, SIGNAL(showAllChanged(bool)),
             this, SIGNAL(showAllChanged(bool)));
+
+    connect(m_fileStatusWidget, SIGNAL(annotateFiles(QStringList)),
+            this, SIGNAL(annotateFiles(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(diffFiles(QStringList)),
+            this, SIGNAL(diffFiles(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(commitFiles(QStringList)),
+            this, SIGNAL(commitFiles(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(revertFiles(QStringList)),
+            this, SIGNAL(revertFiles(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(addFiles(QStringList)),
+            this, SIGNAL(addFiles(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(removeFiles(QStringList)),
+            this, SIGNAL(removeFiles(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(redoFileMerges(QStringList)),
+            this, SIGNAL(redoFileMerges(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(markFilesResolved(QStringList)),
+            this, SIGNAL(markFilesResolved(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(ignoreFiles(QStringList)),
+            this, SIGNAL(ignoreFiles(QStringList)));
+
+    connect(m_fileStatusWidget, SIGNAL(unIgnoreFiles(QStringList)),
+            this, SIGNAL(unIgnoreFiles(QStringList)));
+
     addTab(m_fileStatusWidget, tr("My work"));
 
-    // History graph page
+    // History graph tab
     m_historyWidget = new HistoryWidget;
     addTab(m_historyWidget, tr("History"));
 
@@ -116,16 +149,7 @@
 {
     if (!m_fileStatusWidget->haveChangesToCommit()) return false;
     if (!m_fileStatusWidget->getAllUnresolvedFiles().empty()) return false;
-
-    QStringList addable = m_fileStatusWidget->getSelectedAddableFiles();
-    if (addable.empty()) return true;
-
-    QStringList committable = m_fileStatusWidget->getSelectedCommittableFiles();
-
-    // "Removed" files are both committable and addable; don't return
-    // a false negative if the selection only contains these
-    if (committable == addable) return true;
-    return false;
+    return true;
 }
 
 bool HgTabWidget::canRevert() const
@@ -134,35 +158,28 @@
     // unresolved files, but we can't commit them
     if (!m_fileStatusWidget->haveChangesToCommit() &&
         m_fileStatusWidget->getAllUnresolvedFiles().empty()) return false;
-
-    // The rest of this logic is as in canCommit though
-
-    QStringList addable = m_fileStatusWidget->getSelectedAddableFiles();
-    if (addable.empty()) return true;
-
-    QStringList committable = m_fileStatusWidget->getSelectedCommittableFiles();
-    if (committable == addable) return true;
-    return false;
+    return true;
 }
 
 bool HgTabWidget::canAdd() const
 {
+    // Permit this only when work tab is visible
+    if (currentIndex() != 0) return false;
+
     QStringList addable = m_fileStatusWidget->getSelectedAddableFiles();
     if (addable.empty()) return false;
 
     QStringList removable = m_fileStatusWidget->getSelectedRemovableFiles();
     if (!removable.empty()) return false;
 
-    QStringList committable = m_fileStatusWidget->getSelectedCommittableFiles();
-
-    // "Removed" files are both committable and addable; don't return
-    // a false negative if the selection only contains these
-    if (committable == addable || committable.empty()) return true;
-    return false;
+    return true;
 }
 
 bool HgTabWidget::canRemove() const
 {
+    // Permit this only when work tab is visible
+    if (currentIndex() != 0) return false;
+
     if (m_fileStatusWidget->getSelectedRemovableFiles().empty()) return false;
     if (!m_fileStatusWidget->getSelectedAddableFiles().empty()) return false;
     return true;
@@ -170,7 +187,7 @@
 
 bool HgTabWidget::canResolve() const
 {
-    return !m_fileStatusWidget->getSelectedUnresolvedFiles().empty();
+    return !m_fileStatusWidget->getAllUnresolvedFiles().empty();
 }
 
 bool HgTabWidget::haveChangesToCommit() const
@@ -178,41 +195,21 @@
     return m_fileStatusWidget->haveChangesToCommit();
 }
 
-QStringList HgTabWidget::getAllSelectedFiles() const
-{
-    return m_fileStatusWidget->getAllSelectedFiles();
-}
-
 QStringList HgTabWidget::getAllCommittableFiles() const
 {
     return m_fileStatusWidget->getAllCommittableFiles();
 }
 
-QStringList HgTabWidget::getSelectedCommittableFiles() const
-{
-    return m_fileStatusWidget->getSelectedCommittableFiles();
-}
-
 QStringList HgTabWidget::getAllRevertableFiles() const
 {
     return m_fileStatusWidget->getAllRevertableFiles();
 }
 
-QStringList HgTabWidget::getSelectedRevertableFiles() const
-{
-    return m_fileStatusWidget->getSelectedRevertableFiles();
-}
-
 QStringList HgTabWidget::getSelectedAddableFiles() const
 {
     return m_fileStatusWidget->getSelectedAddableFiles();
 }
 
-QStringList HgTabWidget::getAllRemovableFiles() const
-{
-    return m_fileStatusWidget->getAllRemovableFiles();
-}
-
 QStringList HgTabWidget::getSelectedRemovableFiles() const
 {
     return m_fileStatusWidget->getSelectedRemovableFiles();
@@ -223,11 +220,6 @@
     return m_fileStatusWidget->getAllUnresolvedFiles();
 }
 
-QStringList HgTabWidget::getSelectedUnresolvedFiles() const
-{
-    return m_fileStatusWidget->getSelectedUnresolvedFiles();
-}
-
 void HgTabWidget::updateWorkFolderFileList(QString fileList)
 {
     m_fileStates.parseStates(fileList);
--- a/hgtabwidget.h	Wed Mar 02 15:58:34 2011 +0000
+++ b/hgtabwidget.h	Mon Mar 14 10:00:29 2011 +0000
@@ -62,22 +62,12 @@
     bool canResolve() const;
     bool haveChangesToCommit() const;
 
-    QStringList getAllSelectedFiles() const;
-
-    QStringList getSelectedCommittableFiles() const;
     QStringList getAllCommittableFiles() const;
-
-    QStringList getSelectedRevertableFiles() const;
     QStringList getAllRevertableFiles() const;
+    QStringList getAllUnresolvedFiles() const;
 
     QStringList getSelectedAddableFiles() const;
-    QStringList getAllAddableFiles() const;
-
     QStringList getSelectedRemovableFiles() const;
-    QStringList getAllRemovableFiles() const;
-
-    QStringList getSelectedUnresolvedFiles() const;
-    QStringList getAllUnresolvedFiles() const;
 
 signals:
     void selectionChanged();
@@ -98,6 +88,17 @@
     void newBranch(QString id);
     void tag(QString id);
 
+    void annotateFiles(QStringList);
+    void diffFiles(QStringList);
+    void commitFiles(QStringList);
+    void revertFiles(QStringList);
+    void addFiles(QStringList);
+    void removeFiles(QStringList);
+    void redoFileMerges(QStringList);
+    void markFilesResolved(QStringList);
+    void ignoreFiles(QStringList);
+    void unIgnoreFiles(QStringList);
+
 public slots:
     void clearSelections();
     void showWorkTab();
--- a/mainwindow.cpp	Wed Mar 02 15:58:34 2011 +0000
+++ b/mainwindow.cpp	Mon Mar 14 10:00:29 2011 +0000
@@ -44,6 +44,7 @@
 #include "incomingdialog.h"
 #include "settingsdialog.h"
 #include "moreinformationdialog.h"
+#include "annotatedialog.h"
 #include "version.h"
 #include "workstatuswidget.h"
 
@@ -357,15 +358,12 @@
     m_runner->requestAction(HgAction(ACT_QUERY_PARENTS, m_workFolderPath, params));
 }
 
-void MainWindow::hgAnnotate()
+void MainWindow::hgAnnotateFiles(QStringList files)
 {
     QStringList params;
-    QString currentFile;//!!! = m_hgTabs -> getCurrentFileListLine();
     
-    if (!currentFile.isEmpty())
-    {
-        params << "annotate" << "--" << currentFile.mid(2);   //Jump over status marker characters (e.g "M ")
-
+    if (!files.isEmpty()) {
+        params << "annotate" << "-udqc" << "--" << files;
         m_runner->requestAction(HgAction(ACT_ANNOTATE, m_workFolderPath, params));
     }
 }
@@ -380,12 +378,15 @@
 
 void MainWindow::hgAdd()
 {
-    QStringList params;
-
     // hgExplorer permitted adding "all" files -- I'm not sure
     // that one is a good idea, let's require the user to select
 
-    QStringList files = m_hgTabs->getSelectedAddableFiles();
+    hgAddFiles(m_hgTabs->getSelectedAddableFiles());
+}
+
+void MainWindow::hgAddFiles(QStringList files)
+{
+    QStringList params;
 
     if (!files.empty()) {
         params << "add" << "--" << files;
@@ -393,13 +394,15 @@
     }
 }
 
-
 void MainWindow::hgRemove()
 {
+    hgRemoveFiles(m_hgTabs->getSelectedRemovableFiles());
+}
+
+void MainWindow::hgRemoveFiles(QStringList files)
+{
     QStringList params;
 
-    QStringList files = m_hgTabs->getSelectedRemovableFiles();
-
     if (!files.empty()) {
         params << "remove" << "--after" << "--force" << "--" << files;
         m_runner->requestAction(HgAction(ACT_REMOVE, m_workFolderPath, params));
@@ -408,6 +411,11 @@
 
 void MainWindow::hgCommit()
 {
+    hgCommitFiles(QStringList());
+}
+
+void MainWindow::hgCommitFiles(QStringList files)
+{
     QStringList params;
     QString comment;
 
@@ -415,7 +423,6 @@
         comment = m_mergeCommitComment;
     }
 
-    QStringList files = m_hgTabs->getSelectedCommittableFiles();
     QStringList allFiles = m_hgTabs->getAllCommittableFiles();
     QStringList reportFiles = files;
     if (reportFiles.empty()) {
@@ -498,7 +505,6 @@
     }
 }
 
-
 void MainWindow::hgNoBranch()
 {
     if (m_currentParents.empty()) return;
@@ -511,7 +517,6 @@
     m_runner->requestAction(HgAction(ACT_NEW_BRANCH, m_workFolderPath, params));
 }
 
-
 void MainWindow::hgTag(QString id)
 {
     QStringList params;
@@ -533,7 +538,6 @@
     }
 }
 
-
 void MainWindow::hgIgnore()
 {
     QString hgIgnorePath;
@@ -568,6 +572,18 @@
     m_runner->requestAction(action);
 }
 
+void MainWindow::hgIgnoreFiles(QStringList files)
+{
+    //!!! not implemented yet
+    DEBUG << "MainWindow::hgIgnoreFiles: Not implemented" << endl;
+}
+
+void MainWindow::hgUnIgnoreFiles(QStringList files)
+{
+    //!!! not implemented yet
+    DEBUG << "MainWindow::hgUnIgnoreFiles: Not implemented" << endl;
+}
+
 QString MainWindow::getDiffBinaryName()
 {
     QSettings settings;
@@ -600,6 +616,11 @@
 
 void MainWindow::hgFolderDiff()
 {
+    hgDiffFiles(QStringList());
+}
+
+void MainWindow::hgDiffFiles(QStringList files)
+{
     QString diff = getDiffBinaryName();
     if (diff == "") return;
 
@@ -610,12 +631,11 @@
     params << "--config" << "extensions.extdiff=" << "extdiff";
     params << "--program" << diff;
 
-    params << m_hgTabs->getSelectedCommittableFiles(); // may be none: whole dir
+    params << "--" << files; // may be none: whole dir
 
     m_runner->requestAction(HgAction(ACT_FOLDERDIFF, m_workFolderPath, params));
 }
 
-
 void MainWindow::hgDiffToCurrent(QString id)
 {
     QString diff = getDiffBinaryName();
@@ -632,7 +652,6 @@
     m_runner->requestAction(HgAction(ACT_FOLDERDIFF, m_workFolderPath, params));
 }
 
-
 void MainWindow::hgDiffToParent(QString child, QString parent)
 {
     QString diff = getDiffBinaryName();
@@ -649,7 +668,7 @@
 
     m_runner->requestAction(HgAction(ACT_CHGSETDIFF, m_workFolderPath, params));
 }
-
+    
 
 void MainWindow::hgShowSummaryFor(Changeset *cs)
 {
@@ -687,11 +706,15 @@
 
 void MainWindow::hgRevert()
 {
+    hgRevertFiles(QStringList());
+}
+
+void MainWindow::hgRevertFiles(QStringList files)
+{
     QStringList params;
     QString comment;
     bool all = false;
 
-    QStringList files = m_hgTabs->getSelectedRevertableFiles();
     QStringList allFiles = m_hgTabs->getAllRevertableFiles();
     if (files.empty() || files == allFiles) {
         files = allFiles;
@@ -758,7 +781,7 @@
 }
 
 
-void MainWindow::hgMarkResolved(QStringList files)
+void MainWindow::hgMarkFilesResolved(QStringList files)
 {
     QStringList params;
 
@@ -774,7 +797,13 @@
 }
 
 
-void MainWindow::hgRetryMerge()
+void MainWindow::hgRedoMerge()
+{
+    hgRedoFileMerges(QStringList());
+}
+
+
+void MainWindow::hgRedoFileMerges(QStringList files)
 {
     QStringList params;
 
@@ -785,7 +814,6 @@
         params << "--tool" << merge;
     }
 
-    QStringList files = m_hgTabs->getSelectedUnresolvedFiles();
     if (files.empty()) {
         params << "--all";
     } else {
@@ -800,12 +828,12 @@
 
     m_mergeCommitComment = tr("Merge");
 }
-
+    
 
 void MainWindow::hgMerge()
 {
     if (m_hgTabs->canResolve()) {
-        hgRetryMerge();
+        hgRedoMerge();
         return;
     }
 
@@ -1427,49 +1455,6 @@
     }
 }
 
-#define STDOUT_NEEDS_BIG_WINDOW 512
-#define SMALL_WND_W     500
-#define SMALL_WND_H     300
-
-#define BIG_WND_W       1024
-#define BIG_WND_H       768
-
-
-void MainWindow::presentLongStdoutToUser(QString stdo)
-{
-    if (!stdo.isEmpty())
-    {
-        QDialog dlg;
-
-        if (stdo.length() > STDOUT_NEEDS_BIG_WINDOW)
-        {
-            dlg.setMinimumWidth(BIG_WND_W);
-            dlg.setMinimumHeight(BIG_WND_H);
-        }
-        else
-        {
-            dlg.setMinimumWidth(SMALL_WND_W);
-            dlg.setMinimumHeight(SMALL_WND_H);
-        }
-
-        QVBoxLayout *box = new QVBoxLayout;
-        QListWidget *list = new QListWidget;
-        list-> addItems(stdo.split("\n"));
-        QPushButton *btn = new QPushButton(tr("Ok"));
-        connect(btn, SIGNAL(clicked()), &dlg, SLOT(accept()));
-
-        box -> addWidget(list);
-        box -> addWidget(btn);
-        dlg.setLayout(box);
-
-        dlg.exec();
-    }
-    else
-    {
-        QMessageBox::information(this, tr("EasyMercurial"), tr("Mercurial command did not return any output."));
-    }
-}
-
 void MainWindow::updateFileSystemWatcher()
 {
     bool justCreated = false;
@@ -1667,7 +1652,7 @@
     int n = extractChangeCount(output);
     if (n > 0) {
         head = tr("Pulled %n changeset(s)", "", n);
-        report = tr("The new changes will be highlighted in the history.<br>Use Update to bring these changes into your working copy.");
+        report = tr("New changes will be highlighted in yellow in the history.");
     } else if (n == 0) {
         head = tr("No changes to pull");
         report = tr("Your local repository already contains all changes found in the remote repository.");
@@ -1778,7 +1763,7 @@
         // if clone fails, we have no repo
         m_workFolderPath = "";
         enableDisableActions();
-        break;
+        break; // go on to default report
     case ACT_INCOMING:
         // returns non-zero code and no output if the check was
         // successful but there are no changes pending
@@ -1786,7 +1771,7 @@
             showIncoming("");
             return;
         }
-        break;
+        break; // go on to default report
     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
@@ -1805,8 +1790,16 @@
             reportNewRemoteHeads(output);
             return;
         }
+        break; // go on to default report
+    case ACT_MERGE:
+    case ACT_RETRY_MERGE:
+        MoreInformationDialog::information
+            (this, tr("Merge"), tr("Merge failed"),
+             tr("Some files were not merged successfully.<p>You can Merge again to repeat the interactive merge; use Revert to abandon the merge entirely; or edit the files that are in conflict in an editor and, when you are happy with them, choose Mark Resolved in each file's right-button menu."),
+             output);
+        return;
     case ACT_STAT:
-        break; // go on and report
+        break; // go on to default report
     default:
         break;
     }
@@ -1895,9 +1888,12 @@
         break;
 
     case ACT_ANNOTATE:
-        presentLongStdoutToUser(output);
+    {
+        AnnotateDialog dialog(this, output);
+        dialog.exec();
         m_shouldHgStat = true;
         break;
+    }
         
     case ACT_PULL:
         showPullResult(output);
@@ -1970,7 +1966,7 @@
         break;
 
     case ACT_REVERT:
-        hgMarkResolved(m_lastRevertedFiles);
+        hgMarkFilesResolved(m_lastRevertedFiles);
         m_justMerged = false;
         break;
         
@@ -2175,12 +2171,14 @@
     connect(m_hgPullAct, SIGNAL(triggered()), this, SLOT(hgPull()));
     connect(m_hgPushAct, SIGNAL(triggered()), this, SLOT(hgPush()));
 
-    connect(m_hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate()));
     connect(m_hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe()));
 }
 
 void MainWindow::connectTabsSignals()
 {
+    connect(m_hgTabs, SIGNAL(currentChanged(int)),
+            this, SLOT(enableDisableActions()));
+
     connect(m_hgTabs, SIGNAL(commit()),
             this, SLOT(hgCommit()));
     
@@ -2219,6 +2217,36 @@
 
     connect(m_hgTabs, SIGNAL(tag(QString)),
             this, SLOT(hgTag(QString)));
+
+    connect(m_hgTabs, SIGNAL(annotateFiles(QStringList)),
+            this, SLOT(hgAnnotateFiles(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(diffFiles(QStringList)),
+            this, SLOT(hgDiffFiles(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(commitFiles(QStringList)),
+            this, SLOT(hgCommitFiles(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(revertFiles(QStringList)),
+            this, SLOT(hgRevertFiles(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(addFiles(QStringList)),
+            this, SLOT(hgAddFiles(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(removeFiles(QStringList)),
+            this, SLOT(hgRemoveFiles(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(redoFileMerges(QStringList)),
+            this, SLOT(hgRedoFileMerges(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(markFilesResolved(QStringList)),
+            this, SLOT(hgMarkFilesResolved(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(ignoreFiles(QStringList)),
+            this, SLOT(hgIgnoreFiles(QStringList)));
+
+    connect(m_hgTabs, SIGNAL(unIgnoreFiles(QStringList)),
+            this, SLOT(hgUnIgnoreFiles(QStringList)));
 }    
 
 void MainWindow::enableDisableActions()
@@ -2283,7 +2311,6 @@
     m_hgUpdateAct -> setEnabled(m_localRepoActionsEnabled);
     m_hgCommitAct -> setEnabled(m_localRepoActionsEnabled);
     m_hgMergeAct -> setEnabled(m_localRepoActionsEnabled);
-    m_hgAnnotateAct -> setEnabled(m_localRepoActionsEnabled);
     m_hgServeAct -> setEnabled(m_localRepoActionsEnabled);
     m_hgIgnoreAct -> setEnabled(m_localRepoActionsEnabled);
 
@@ -2459,9 +2486,6 @@
     m_hgMergeAct->setStatusTip(tr("Merge the two independent sets of changes in the local repository into the working folder"));
 
     //Advanced actions
-    //!!! needs to be modified for number
-    m_hgAnnotateAct = new QAction(tr("Annotate"), this);
-    m_hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file"));
 
     m_hgIgnoreAct = new QAction(tr("Edit .hgignore File"), this);
     m_hgIgnoreAct -> setStatusTip(tr("Edit the .hgignore file, containing the names of files that should be ignored by Mercurial"));
--- a/mainwindow.h	Wed Mar 02 15:58:34 2011 +0000
+++ b/mainwindow.h	Mon Mar 14 10:00:29 2011 +0000
@@ -78,8 +78,7 @@
     void hgUpdate();
     void hgRevert();
     void hgMerge();
-    void hgMarkResolved(QStringList);
-    void hgRetryMerge();
+    void hgRedoMerge();
     void hgCloneFromRemote();
     void hgInit();
     void hgIncoming();
@@ -87,7 +86,6 @@
     void hgPull();
     void hgUpdateToRev(QString);
     void hgMergeFrom(QString);
-    void hgAnnotate();
     void hgResolveList();
     void hgTag(QString);
     void hgNewBranch();
@@ -95,6 +93,17 @@
     void hgServe();
     void hgIgnore();
 
+    void hgAnnotateFiles(QStringList);
+    void hgDiffFiles(QStringList);
+    void hgCommitFiles(QStringList);
+    void hgRevertFiles(QStringList);
+    void hgAddFiles(QStringList);
+    void hgRemoveFiles(QStringList);
+    void hgRedoFileMerges(QStringList);
+    void hgMarkFilesResolved(QStringList);
+    void hgIgnoreFiles(QStringList);
+    void hgUnIgnoreFiles(QStringList);
+
     void fsDirectoryChanged(QString);
     void fsFileChanged(QString);
     void checkFilesystem();
@@ -116,7 +125,6 @@
     void readSettings();
     void splitChangeSets(QStringList *list, QString hgLogOutput);
     void reportNewRemoteHeads(QString);
-    void presentLongStdoutToUser(QString stdo);
     void writeSettings();
 
     QStringList listAllUpIpV4Addresses();
--- a/version.h	Wed Mar 02 15:58:34 2011 +0000
+++ b/version.h	Mon Mar 14 10:00:29 2011 +0000
@@ -1,1 +1,1 @@
-#define EASYHG_VERSION "0.4"
+#define EASYHG_VERSION "0.9"