changeset 210:c5fceb3fe5b4

* OS/X: Add script to run external diff; add space around tab widget; textual fixes * Bail out of easyhg.py in uisetup rather than at extension load time if we can't load PyQt4 -- that way we find out about it in easyhg * Ensure editing the default path works even if hgrc doesn't yet exist; ensure path and branch are reset (to empty and default) if their respective files are absent
author Chris Cannam
date Wed, 05 Jan 2011 14:31:07 +0000
parents 0b040abb2aa3
children 290a95b5ceae
files easyhg-extdiff-osx.sh easyhg.py filestatuswidget.cpp hgrunner.cpp mainwindow.cpp
diffstat 5 files changed, 101 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easyhg-extdiff-osx.sh	Wed Jan 05 14:31:07 2011 +0000
@@ -0,0 +1,9 @@
+#!/bin/bash
+if [ $# -lt 2 ]; then 
+    echo Insufficient arguments: $@
+    exit 2
+fi
+while [ $# -gt 2 ]; do
+    shift
+done
+/usr/bin/opendiff "$1" "$2"
--- a/easyhg.py	Tue Jan 04 16:34:33 2011 +0000
+++ b/easyhg.py	Wed Jan 05 14:31:07 2011 +0000
@@ -26,11 +26,24 @@
 if not easyhg_import_path.startswith('NO_'):
     sys.path.append(easyhg_import_path)
 
-from PyQt4 import QtGui
+# Try to load the PyQt4 module that we need.  If this fails, we should
+# bail out later (in uisetup), because if we bail out now, Mercurial
+# will just continue without us and report success.  The invoking
+# application needs to be able to discover whether the module load
+# succeeded or not, so we need to ensure that Mercurial itself returns
+# failure if it didn't.
+#
+easyhg_pyqt_ok = True
+try:
+    from PyQt4 import QtGui
+except ImportError as err:
+    easyhg_pyqt_ok = False
 
 easyhg_qtapp = None
 
 def uisetup(ui):
+    if not easyhg_pyqt_ok:
+        raise util.Abort(_('Failed to load PyQt4 module required by easyhg.py'))
     ui.__class__.prompt = easyhg_prompt
     ui.__class__.getpass = easyhg_getpass
     global easyhg_qtapp
--- a/filestatuswidget.cpp	Tue Jan 04 16:34:33 2011 +0000
+++ b/filestatuswidget.cpp	Wed Jan 05 14:31:07 2011 +0000
@@ -69,8 +69,9 @@
     layout->addWidget(new QLabel("<qt><hr></qt>"), ++row, 0, 1, 3);
 
     ++row;
+    //!!! option to be less verbose -> shorten this
     m_noModificationsLabel = new QLabel
-        (tr("<qt>This area will list files in your working folder that you have changed.<br>At the moment you have no uncommitted changes.<br><br>To see changes made to the repository previously,<br>switch to the History tab.<br><br>%1</qt>")
+        (tr("<qt>This area will list files in your working folder that you have changed.<br><br>At the moment you have no uncommitted changes.<br><br>To see changes previously made to the repository,<br>switch to the History tab.<br><br>%1</qt>")
 #if defined Q_OS_MAC
          .arg(tr("To open the working folder in Finder,<br>click on the &ldquo;Local&rdquo; folder path shown above."))
 #elif defined Q_OS_WIN32
--- a/hgrunner.cpp	Tue Jan 04 16:34:33 2011 +0000
+++ b/hgrunner.cpp	Wed Jan 05 14:31:07 2011 +0000
@@ -65,21 +65,18 @@
 
 QString HgRunner::findExtension()
 {
-    // If we haven't unbundled an extension, always do that (so that
-    // it's available in case someone wants to use it later, e.g. to
-    // fix a malfunctioning setup).  But the path we actually prefer
-    // is the one in the settings first, if it exists; then the
+    // Always unbundle the extension: even if it already exists (in
+    // case we're upgrading) and even if we're not going to use it (so
+    // that it's available in case someone wants to use it later,
+    // e.g. to fix a malfunctioning setup).  But the path we actually
+    // prefer is the one in the settings first, if it exists; then the
     // unbundled one; then anything in the path if for some reason
     // unbundling failed
 
     QSettings settings;
     settings.beginGroup("Locations");
 
-    QString unbundled = getUnbundledFileName();
-    if (!QFile(unbundled).exists()) {
-        unbundled = unbundleExtension();
-    }
-
+    QString unbundled = unbundleExtension();
     QString extpath = settings.value("extensionpath", "").toString();
     if (extpath != "" && QFile(extpath).exists()) return extpath;
 
--- a/mainwindow.cpp	Tue Jan 04 16:34:33 2011 +0000
+++ b/mainwindow.cpp	Wed Jan 05 14:31:07 2011 +0000
@@ -76,9 +76,23 @@
     readSettings();
 
     justMerged = false;
-    hgTabs = new HgTabWidget((QWidget *) this, remoteRepoPath, workFolderPath);
+
+    QWidget *central = new QWidget(this);
+    setCentralWidget(central);
+
+    hgTabs = new HgTabWidget(central, remoteRepoPath, workFolderPath);
     connectTabsSignals();
-    setCentralWidget(hgTabs);
+
+    // 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(hgTabs, 0, 0);
+
+#ifndef Q_OS_MAC
+    cl->setMargin(0);
+#endif
 
     connect(hgTabs, SIGNAL(selectionChanged()),
             this, SLOT(enableDisableActions()));
@@ -225,51 +239,61 @@
 
 void MainWindow::hgQueryPaths()
 {
-    // Quickest is to just read the file -- but fall back on hg
-    // command if we get confused
+    // Quickest is to just read the file
 
     QFileInfo hgrc(workFolderPath + "/.hg/hgrc");
 
+    QString path;
+
     if (hgrc.exists()) {
-
         QSettings s(hgrc.canonicalFilePath(), QSettings::IniFormat);
         s.beginGroup("paths");
-        remoteRepoPath = s.value("default").toString();
+        path = s.value("default").toString();
+    }
 
-        // We have to do this here, because commandCompleted won't be called
-        MultiChoiceDialog::addRecentArgument("local", workFolderPath);
-        MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath);
-        hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath);
+    remoteRepoPath = path;
 
-        hgQueryBranch();
-        return;
-    }
+    // We have to do this here, because commandCompleted won't be called
+    MultiChoiceDialog::addRecentArgument("local", workFolderPath);
+    MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath);
+    hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath);
+    
+    hgQueryBranch();
+    return;
+
+/* The classic method!
 
     QStringList params;
     params << "paths";
     runner->requestAction(HgAction(ACT_QUERY_PATHS, workFolderPath, params));
+*/
 }
 
 void MainWindow::hgQueryBranch()
 {
-    // Quickest is to just read the file -- but fall back on hg
-    // command if we get confused
+    // Quickest is to just read the file
 
     QFile hgbr(workFolderPath + "/.hg/branch");
 
+    QString br = "default";
+
     if (hgbr.exists() && hgbr.open(QFile::ReadOnly)) {
+        QByteArray ba = hgbr.readLine();
+        br = QString::fromUtf8(ba).trimmed();
+    }
+    
+    currentBranch = br;
+    
+    // We have to do this here, because commandCompleted won't be called
+    hgStat();
+    return;
 
-        QByteArray ba = hgbr.readLine();
-        currentBranch = QString::fromUtf8(ba).trimmed();
-        
-        // We have to do this here, because commandCompleted won't be called
-        hgStat();
-        return;
-    }
+/* The classic method!
 
     QStringList params;
     params << "branch";
     runner->requestAction(HgAction(ACT_QUERY_BRANCH, workFolderPath, params));
+*/
 }
 
 void MainWindow::hgQueryHeads()
@@ -481,7 +505,7 @@
     QString diff = settings.value("extdiffbinary", "").toString();
     if (diff == "") {
         QStringList bases;
-        bases << "opendiff" << "kompare" << "kdiff3" << "meld";
+        bases << "easyhg-extdiff-osx.sh" << "kompare" << "kdiff3" << "meld";
         bool found = false;
         foreach (QString base, bases) {
             diff = findInPath(base, m_myDirPath, true);
@@ -1024,9 +1048,18 @@
                  MultiChoiceDialog::UrlArg);
 
     if (d->exec() == QDialog::Accepted) {
-        QSettings s(hgrc.canonicalFilePath(), QSettings::IniFormat);
-        s.beginGroup("paths");
-        s.setValue("default", d->getArgument());
+
+        // New block to ensure QSettings is deleted before
+        // hgQueryPaths called.  NB use of absoluteFilePath instead of
+        // canonicalFilePath, which would fail if the file did not yet
+        // exist
+
+        {
+            QSettings s(hgrc.absoluteFilePath(), QSettings::IniFormat);
+            s.beginGroup("paths");
+            s.setValue("default", d->getArgument());
+        }
+
         stateUnknown = true;
         hgQueryPaths();
     }
@@ -1486,6 +1519,13 @@
 {
     DEBUG << "MainWindow::commandFailed" << endl;
 
+    QString setstr;
+#ifdef Q_OS_MAC
+    setstr = tr("Preferences");
+#else
+    setstr = tr("Settings");
+#endif
+
     // Some commands we just have to ignore bad return values from:
 
     switch(action.action) {
@@ -1496,7 +1536,7 @@
         QMessageBox::warning
             (this, tr("Failed to run Mercurial"),
              format3(tr("Failed to run Mercurial"),
-                     tr("The Mercurial program either could not be found or failed to run.<br>Check that the Mercurial program path is correct in Settings.<br><br>%1").arg(output == "" ? QString("") : tr("The test command said:")),
+                     tr("The Mercurial program either could not be found or failed to run.<br>Check that the Mercurial program path is correct in %1.<br><br>%2").arg(setstr).arg(output == "" ? QString("") : tr("The test command said:")),
                      output));
         settings();
         return;
@@ -1504,7 +1544,7 @@
         QMessageBox::warning
             (this, tr("Failed to run Mercurial"),
              format3(tr("Failed to run Mercurial with extension enabled"),
-                     tr("The Mercurial program failed to run with the EasyMercurial interaction extension enabled.<br>This may indicate an installation problem with EasyMercurial.<br><br>You may be able to continue working if you switch off &ldquo;Use EasyHg Mercurial Extension&rdquo; in Settings.  Note that remote repositories that require authentication may not work if you do this.<br><br>%1").arg(output == "" ? QString("") : tr("The test command said:")),
+                     tr("The Mercurial program failed to run with the EasyMercurial interaction extension enabled.<br>This may indicate an installation problem with EasyMercurial.<br><br>You may be able to continue working if you switch off &ldquo;Use EasyHg Mercurial Extension&rdquo; in %1.  Note that remote repositories that require authentication may not work if you do this.<br><br>%2").arg(setstr).arg(output == "" ? QString("") : tr("The test command said:")),
                      output));
         settings();
         return;
@@ -1584,6 +1624,8 @@
         if (!ll.empty()) {
             remoteRepoPath = lp.parse()[0]["default"].trimmed();
             DEBUG << "Set remote path to " << remoteRepoPath << endl;
+        } else {
+            remoteRepoPath = "";
         }
         MultiChoiceDialog::addRecentArgument("local", workFolderPath);
         MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath);