changeset 74:10eb97683aa9

* Show branch names even for changes with children, if those children are on a different branch * Pick up remote repo path from local repo via hg paths * Some work towards breaking down files into various groups based on status * Add /usr/local/bin to path for hg (temporary hack I hope)
author Chris Cannam
date Fri, 19 Nov 2010 14:54:19 +0000
parents a773c6e7b301
children 295e3ee4a257
files changesetitem.cpp changesetitem.h common.cpp easyhg.pro grapher.cpp hgrunner.cpp logparser.cpp logparser.h mainwindow.cpp mainwindow.h multichoicedialog.cpp multichoicedialog.h statparser.cpp statparser.h
diffstat 14 files changed, 181 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/changesetitem.cpp	Thu Nov 18 18:08:18 2010 +0000
+++ b/changesetitem.cpp	Fri Nov 19 14:54:19 2010 +0000
@@ -23,7 +23,7 @@
 #include <QPainter>
 
 ChangesetItem::ChangesetItem(Changeset *cs) :
-    m_changeset(cs), m_column(0), m_row(0), m_wide(false)
+    m_changeset(cs), m_showBranch(false), m_column(0), m_row(0), m_wide(false)
 {
     m_font = QFont();
     m_font.setPixelSize(11);
@@ -93,11 +93,12 @@
 
     paint->setPen(QPen(Qt::black));
 
-    if (m_changeset->children().empty()) {
+    if (m_showBranch) {
 	// write branch name
 	f.setBold(true);
 	paint->setFont(f);
 	QString branch = m_changeset->branch();
+        if (branch == "") branch = "default";
 	int wid = width - 3;
 	branch = TextAbbrev::abbreviate(branch, QFontMetrics(f), wid);
 	paint->drawText(x0, -fh + fm.ascent() - 4, branch);
--- a/changesetitem.h	Thu Nov 18 18:08:18 2010 +0000
+++ b/changesetitem.h	Fri Nov 19 14:54:19 2010 +0000
@@ -41,9 +41,13 @@
     bool isWide() const { return m_wide; }
     void setWide(bool w) { m_wide = w; }
 
+    bool shouldShowBranch() const { return m_showBranch; }
+    void setShowBranch(bool s) { m_showBranch = s; }
+
 private:
     QFont m_font;
     Changeset *m_changeset;
+    bool m_showBranch;
     int m_column;
     int m_row;
     bool m_wide;
--- a/common.cpp	Thu Nov 18 18:08:18 2010 +0000
+++ b/common.cpp	Fri Nov 19 14:54:19 2010 +0000
@@ -33,7 +33,12 @@
             QString path =
                 QProcessEnvironment::systemEnvironment().value("PATH");
             DEBUG << "findExecutable: seeking location for binary " << name
-                  << ": system path is " << path;
+                  << ": system path is " << path << endl;
+#ifndef Q_OS_WIN32
+            path = path + ":/usr/local/bin";
+            DEBUG << "... adding /usr/local/bin just in case (fix and add settings dlg please)"
+                    << endl;
+#endif
 #ifdef Q_OS_WIN32
             QChar pathSep = ';';
 #else
--- a/easyhg.pro	Thu Nov 18 18:08:18 2010 +0000
+++ b/easyhg.pro	Fri Nov 19 14:54:19 2010 +0000
@@ -30,7 +30,8 @@
     startupdialog.h \
     repositorydialog.h \
     multichoicedialog.h \
-    selectablelabel.h
+    selectablelabel.h \
+    statparser.h
 SOURCES = main.cpp \
     mainwindow.cpp \
     hgexpwidget.cpp \
@@ -52,7 +53,8 @@
     startupdialog.cpp \
     repositorydialog.cpp \
     multichoicedialog.cpp \
-    selectablelabel.cpp
+    selectablelabel.cpp \
+    statparser.cpp
 
 macx-* {
     SOURCES += common_osx.mm
--- a/grapher.cpp	Thu Nov 18 18:08:18 2010 +0000
+++ b/grapher.cpp	Fri Nov 19 14:54:19 2010 +0000
@@ -353,6 +353,8 @@
         m_scene->addItem(item);
     }
 
+    // Add the connecting lines
+
     foreach (Changeset *cs, csets) {
 	QString id = cs->id();
 	ChangesetItem *item = m_items[id];
@@ -369,6 +371,21 @@
 	}
     }
 
+    // Add the branch labels
+    foreach (Changeset *cs, csets) {
+        QString id = cs->id();
+        ChangesetItem *item = m_items[id];
+        bool haveChildOnSameBranch = false;
+        foreach (QString childId, cs->children()) {
+            Changeset *child = m_changesets[childId];
+            if (child->branch() == cs->branch()) {
+                haveChildOnSameBranch = true;
+                break;
+            }
+        }
+        item->setShowBranch(!haveChildOnSameBranch);
+    }
+
     // We need to lay out the changesets in forward chronological
     // order.  We have no guarantees about the order in which
     // changesets appear in the list -- in a simple repository they
--- a/hgrunner.cpp	Thu Nov 18 18:08:18 2010 +0000
+++ b/hgrunner.cpp	Fri Nov 19 14:54:19 2010 +0000
@@ -99,9 +99,11 @@
     saveOutput();
     isRunning = false;
 
-    if (procExitCode == 0 || procExitStatus == QProcess::NormalExit) {
+    if (procExitCode == 0 && procExitStatus == QProcess::NormalExit) {
+        DEBUG << "HgRunner::finished: Command completed successfully: stderr says: " << stdErr << endl;
         emit commandCompleted();
     } else {
+        DEBUG << "HgRunner::finished: Command failed: stderr says: " << stdErr << endl;
         emit commandFailed();
     }
 }
--- a/logparser.cpp	Thu Nov 18 18:08:18 2010 +0000
+++ b/logparser.cpp	Fri Nov 19 14:54:19 2010 +0000
@@ -17,10 +17,13 @@
 
 #include "logparser.h"
 
+#include "debug.h"
+
 #include <QStringList>
 #include <QRegExp>
 
-LogParser::LogParser(QString text) : m_text(text)
+LogParser::LogParser(QString text, QString separator) :
+    m_text(text), m_sep(separator)
 {
     m_text.replace("\r\n", "\n");
 }
@@ -33,7 +36,7 @@
 LogList LogParser::parse()
 {
     LogList results;
-    QRegExp re("^(\\w+):\\s+(.*)$");
+    QRegExp re(QString("^(\\w+)\\s*%1\\s+(.*)$").arg(m_sep));
     QStringList entries = split();
     foreach (QString entry, entries) {
         LogEntry dictionary;
@@ -42,7 +45,7 @@
             if (re.indexIn(line) == 0) {
                 QString key = re.cap(1);
                 QString value = re.cap(2);
-                dictionary[key] = value;
+                dictionary[key.trimmed()] = value;
             }
         }
         results.push_back(dictionary);
--- a/logparser.h	Thu Nov 18 18:08:18 2010 +0000
+++ b/logparser.h	Fri Nov 19 14:54:19 2010 +0000
@@ -29,13 +29,14 @@
 class LogParser : public QObject
 {
 public:
-    LogParser(QString text);
+    LogParser(QString text, QString separator = ":");
 
     QStringList split();
     LogList parse();
 
 private:
     QString m_text;
+    QString m_sep;
 };
 
 #endif // LOGPARSER_H
--- a/mainwindow.cpp	Thu Nov 18 18:08:18 2010 +0000
+++ b/mainwindow.cpp	Fri Nov 19 14:54:19 2010 +0000
@@ -35,6 +35,7 @@
 #include "startupdialog.h"
 #include "colourset.h"
 #include "debug.h"
+#include "logparser.h"
 
 
 MainWindow::MainWindow()
@@ -83,7 +84,7 @@
         open();
     }
 
-    hgStat();
+    hgPaths();
 }
 
 
@@ -148,6 +149,17 @@
     }
 }
 
+void MainWindow::hgPaths()
+{
+    if (runningAction == ACT_NONE)
+    {
+        QStringList params;
+        params << "paths";
+        runner -> startHgCommand(workFolderPath, params);
+        runningAction = ACT_PATHS;
+    }
+}
+
 void MainWindow::hgHeads()
 {
     if (runningAction == ACT_NONE)
@@ -739,7 +751,7 @@
         
         hgExp->clearLists();
         enableDisableActions();
-        hgStat();
+        hgPaths();
     }
 
     delete d;
@@ -981,6 +993,10 @@
 void MainWindow::commandFailed()
 {
     DEBUG << "MainWindow::commandFailed" << endl;
+    runningAction = ACT_NONE;
+    runner -> hideProgBar();
+
+    //!!! N.B hg incoming returns failure even if successful, if there were no changes
 }
 
 void MainWindow::commandCompleted()
@@ -1003,8 +1019,24 @@
                 //Successful running.
                 switch(runningAction)
                 {
+                    case ACT_PATHS:
+                    {
+                        QString stdout = runner->getStdOut();
+                        DEBUG << "stdout is " << stdout << endl;
+                        LogParser lp(stdout, "=");
+                        LogList ll = lp.parse();
+                        DEBUG << ll.size() << " results" << endl;
+                        if (!ll.empty()) {
+                            remoteRepoPath = lp.parse()[0]["default"].trimmed();
+                            DEBUG << "Set remote path to " << remoteRepoPath << endl;
+                        }
+                        MultiChoiceDialog::addRecentArgument("local", workFolderPath);
+                        MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath);
+                        enableDisableActions();
+                        break;
+                    }
+
                     case ACT_STAT:
-                        MultiChoiceDialog::addRecentArgument("local", workFolderPath);
                         hgExp -> updateWorkFolderFileList(runner -> getStdOut());
                         break;
 
@@ -1097,8 +1129,13 @@
             }
 
 
-            //Typical sequence goes stat -> heads -> parents -> log
-            if (runningAction == ACT_STAT)
+            //Typical sequence goes paths -> stat -> heads -> parents -> log
+            if (runningAction == ACT_PATHS)
+            {
+                runningAction = ACT_NONE;
+                hgStat();
+            }
+            else if (runningAction == ACT_STAT)
             {
                 runningAction = ACT_NONE;
                 hgHeads();
@@ -1132,7 +1169,7 @@
                 runningAction = ACT_NONE;
                 if (shouldHgStat)
                 {
-                    hgStat();
+                    hgPaths();
                 }
             }
         }
@@ -1149,8 +1186,8 @@
     connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
     connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
 
-    connect(hgStatAct, SIGNAL(triggered()), this, SLOT(hgStat()));
-    connect(hgExp, SIGNAL(workFolderViewTypesChanged()), this, SLOT(hgStat()));
+    connect(hgStatAct, SIGNAL(triggered()), this, SLOT(hgPaths()));
+    connect(hgExp, SIGNAL(workFolderViewTypesChanged()), this, SLOT(hgPaths()));
     connect(hgRemoveAct, SIGNAL(triggered()), this, SLOT(hgRemove()));
     connect(hgAddAct, SIGNAL(triggered()), this, SLOT(hgAdd()));
     connect(hgCommitAct, SIGNAL(triggered()), this, SLOT(hgCommit()));
--- a/mainwindow.h	Thu Nov 18 18:08:18 2010 +0000
+++ b/mainwindow.h	Fri Nov 19 14:54:19 2010 +0000
@@ -33,6 +33,7 @@
 enum HGACTIONS
 {
     ACT_NONE,
+    ACT_PATHS,
     ACT_STAT,
     ACT_HEADS,
     ACT_PARENTS,
@@ -80,6 +81,7 @@
     void closeEvent(QCloseEvent *event);
 
 public slots:
+    void hgPaths();
     void hgStat();
     void tabChanged(int currTab);
     void commandCompleted();
--- a/multichoicedialog.cpp	Thu Nov 18 18:08:18 2010 +0000
+++ b/multichoicedialog.cpp	Fri Nov 19 14:54:19 2010 +0000
@@ -52,20 +52,24 @@
     f.setPointSize(f.pointSize() * 0.9);
     m_descriptionLabel->setFont(f);
 
-    m_urlLabel = new QLabel(tr("URL:"));
+    m_urlLabel = new QLabel(tr("&URL:"));
     outer->addWidget(m_urlLabel, 3, 0);
 
     m_urlCombo = new QComboBox();
     m_urlCombo->setEditable(true);
+    m_urlLabel->setBuddy(m_urlCombo);
     connect(m_urlCombo, SIGNAL(editTextChanged(const QString &)),
             this, SLOT(urlChanged(const QString &)));
     outer->addWidget(m_urlCombo, 3, 1, 1, 2);
 
-    m_fileLabel = new QLabel(tr("File:"));
+    m_fileLabel = new QLabel(tr("&File:"));
     outer->addWidget(m_fileLabel, 4, 0);
 
     m_fileCombo = new QComboBox();
     m_fileCombo->setEditable(true);
+    m_fileLabel->setBuddy(m_fileCombo);
+    connect(m_fileCombo, SIGNAL(editTextChanged(const QString &)),
+            this, SLOT(fileChanged(const QString &)));
     outer->addWidget(m_fileCombo, 4, 1);
     outer->setColumnStretch(1, 20);
 
@@ -78,7 +82,10 @@
     connect(bbox, SIGNAL(accepted()), this, SLOT(accept()));
     connect(bbox, SIGNAL(rejected()), this, SLOT(reject()));
     outer->addWidget(bbox, 5, 0, 1, 3);
-    
+
+    m_okButton = bbox->button(QDialogButtonBox::Ok);
+    m_okButton->setEnabled(false);
+
     setMinimumWidth(480);
 }
 
@@ -215,6 +222,17 @@
 }
 
 void
+MultiChoiceDialog::fileChanged(const QString &s)
+{
+    if (m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
+        m_okButton->setEnabled(getArgument() != "" &&
+                               getAdditionalArgument() != "");
+    } else {
+        m_okButton->setEnabled(getArgument() != "");
+    }
+}
+
+void
 MultiChoiceDialog::choiceChanged()
 {
     DEBUG << "choiceChanged" << endl;
@@ -263,7 +281,7 @@
         break;
 
     case FileArg:
-        m_fileLabel->setText(tr("File:"));
+        m_fileLabel->setText(tr("&File:"));
         m_fileLabel->show();
         m_fileCombo->show();
         m_fileCombo->addItems(rf->getRecent());
@@ -271,7 +289,7 @@
         break;
 
     case DirectoryArg:
-        m_fileLabel->setText(tr("Folder:"));
+        m_fileLabel->setText(tr("&Folder:"));
         m_fileLabel->show();
         m_fileCombo->show();
         m_fileCombo->addItems(rf->getRecent());
@@ -287,7 +305,7 @@
         m_urlLabel->show();
         m_urlCombo->show();
         m_urlCombo->addItems(rf->getRecent());
-        m_fileLabel->setText(tr("Folder:"));
+        m_fileLabel->setText(tr("&Folder:"));
         m_fileLabel->show();
         m_fileCombo->show();
         m_fileCombo->lineEdit()->setText(QDir::homePath());
--- a/multichoicedialog.h	Thu Nov 18 18:08:18 2010 +0000
+++ b/multichoicedialog.h	Fri Nov 19 14:54:19 2010 +0000
@@ -61,6 +61,7 @@
 private slots:
     void choiceChanged();
     void urlChanged(const QString &);
+    void fileChanged(const QString &);
     void browse();
 
 private:
@@ -79,6 +80,7 @@
     QAbstractButton *m_browseButton;
     QLabel *m_urlLabel;
     QComboBox *m_urlCombo;
+    QAbstractButton *m_okButton;
 };
 
 #endif // MULTICHOICEDIALOG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/statparser.cpp	Fri Nov 19 14:54:19 2010 +0000
@@ -0,0 +1,25 @@
+#include "statparser.h"
+
+#include <QMap>
+
+StatParser::StatParser(QString text)
+{
+    text.replace("\r\n", "\n");
+
+    QMap<QChar, QStringList *> buckets;
+    buckets['M'] = &modified;
+    buckets['A'] = &added;
+    buckets['R'] = &removed;
+    buckets['!'] = &missing;
+    buckets['?'] = &unknown;
+
+    QStringList lines = text.split("\n", QString::SkipEmptyParts);
+    foreach (QString line, lines) {
+        if (line.length() < 3 || line[2] != ' ') continue;
+        QChar tag = line[0];
+        QString file = line.right(line.length() - 2);
+        if (buckets.contains(tag)) {
+            buckets[tag]->push_back(file);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/statparser.h	Fri Nov 19 14:54:19 2010 +0000
@@ -0,0 +1,38 @@
+/* -*- 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) 2010 Chris Cannam
+    Copyright (c) 2010 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 STATPARSER_H
+#define STATPARSER_H
+
+#include <QObject>
+#include <QStringList>
+
+class StatParser : public QObject
+{
+    Q_OBJECT
+public:
+    StatParser(QString text);
+
+    QStringList modified;
+    QStringList added;
+    QStringList unknown;
+    QStringList removed;
+    QStringList missing;
+
+};
+
+#endif // STATPARSER_H