# HG changeset patch # User Chris Cannam # Date 1294237867 0 # Node ID c5fceb3fe5b4814b17aa95a5fa2baa1de3b6c4fd # Parent 0b040abb2aa38e306a0da475d7c7e8039bb61ad3 * 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 diff -r 0b040abb2aa3 -r c5fceb3fe5b4 easyhg-extdiff-osx.sh --- /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" diff -r 0b040abb2aa3 -r c5fceb3fe5b4 easyhg.py --- 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 diff -r 0b040abb2aa3 -r c5fceb3fe5b4 filestatuswidget.cpp --- 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("
"), ++row, 0, 1, 3); ++row; + //!!! option to be less verbose -> shorten this m_noModificationsLabel = new QLabel - (tr("This area will list files in your working folder that you have changed.
At the moment you have no uncommitted changes.

To see changes made to the repository previously,
switch to the History tab.

%1
") + (tr("This area will list files in your working folder that you have changed.

At the moment you have no uncommitted changes.

To see changes previously made to the repository,
switch to the History tab.

%1
") #if defined Q_OS_MAC .arg(tr("To open the working folder in Finder,
click on the “Local” folder path shown above.")) #elif defined Q_OS_WIN32 diff -r 0b040abb2aa3 -r c5fceb3fe5b4 hgrunner.cpp --- 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; diff -r 0b040abb2aa3 -r c5fceb3fe5b4 mainwindow.cpp --- 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.
Check that the Mercurial program path is correct in Settings.

%1").arg(output == "" ? QString("") : tr("The test command said:")), + tr("The Mercurial program either could not be found or failed to run.
Check that the Mercurial program path is correct in %1.

%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.
This may indicate an installation problem with EasyMercurial.

You may be able to continue working if you switch off “Use EasyHg Mercurial Extension” in Settings. Note that remote repositories that require authentication may not work if you do this.

%1").arg(output == "" ? QString("") : tr("The test command said:")), + tr("The Mercurial program failed to run with the EasyMercurial interaction extension enabled.
This may indicate an installation problem with EasyMercurial.

You may be able to continue working if you switch off “Use EasyHg Mercurial Extension” in %1. Note that remote repositories that require authentication may not work if you do this.

%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);