From b50c034f4e5b7879e9a4089eebd500e32bc7d08c Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Sat, 10 Feb 2018 20:39:40 +0000 Subject: [PATCH] Python Startup 2 of 2 .. honour PYTHONHOME environment variable .. allow user to set PYTHONHOME in preferences, and check its a decent value before setting it. --- src/Core/Settings.h | 4 +- src/Gui/Pages.cpp | 58 ++++++++++++++++++++++++++- src/Gui/Pages.h | 9 +++++ src/Python/PythonEmbed.cpp | 81 ++++++++++++++++++++++++++------------ src/Python/PythonEmbed.h | 2 +- 5 files changed, 125 insertions(+), 29 deletions(-) diff --git a/src/Core/Settings.h b/src/Core/Settings.h index 8576efd91..ab42c9dea 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -121,9 +121,11 @@ // Colors/Chrome - see special treatment sections (also stored in ) #define GC_CHROME "chrome" // mac or flat only so far -// Location of R Installation +// Location of R Installation - follows R_HOME semantics #define GC_R_HOME "r_home" +// Location of Python Installation - follows PYTHONHOME semantics +#define GC_PYTHON_HOME "pythonhome" // -------------------------------------------------------------------- diff --git a/src/Gui/Pages.cpp b/src/Gui/Pages.cpp index 7453b31a0..9444f4159 100644 --- a/src/Gui/Pages.cpp +++ b/src/Gui/Pages.cpp @@ -45,7 +45,9 @@ #include "LocalFileStore.h" #include "Secrets.h" #include "Utils.h" - +#ifdef GC_WANT_PYTHON +#include "PythonEmbed.h" +#endif extern ConfigDialog *configdialog_ptr; // @@ -190,6 +192,7 @@ GeneralPage::GeneralPage(Context *context) : context(context) embedPython = new QCheckBox(tr("Enable Python"), this); embedPython->setChecked(appsettings->value(NULL, GC_EMBED_PYTHON, true).toBool()); configLayout->addWidget(embedPython, 7+offset,1, Qt::AlignLeft); + connect(embedPython, SIGNAL(stateChanged(int)), this, SLOT(embedPythonchanged(int))); offset += 1; #endif @@ -249,6 +252,24 @@ GeneralPage::GeneralPage(Context *context) : context(context) connect(rBrowseButton, SIGNAL(clicked()), this, SLOT(browseRDir())); #endif +#ifdef GC_WANT_PYTHON + // + // Python Home directory + // + QVariant pythonDir = appsettings->value(this, GC_PYTHON_HOME, ""); + // fix old bug.. + pythonLabel = new QLabel(tr("Python Home")); + pythonDirectory = new QLineEdit; + pythonDirectory->setText(pythonDir.toString()); + pythonBrowseButton = new QPushButton(tr("Browse")); + + configLayout->addWidget(pythonLabel, 8 + offset,0, Qt::AlignRight); + configLayout->addWidget(pythonDirectory, 8 + offset,1); + configLayout->addWidget(pythonBrowseButton, 8 + offset,2); + offset++; + + connect(pythonBrowseButton, SIGNAL(clicked()), this, SLOT(browsePythonDir())); +#endif // save away initial values b4.unit = unitCombo->currentIndex(); @@ -269,6 +290,15 @@ GeneralPage::embedRchanged(int state) rLabel->setVisible(state); } #endif +#ifdef GC_WANT_PYTHON +void +GeneralPage::embedPythonchanged(int state) +{ + pythonBrowseButton->setVisible(state); + pythonDirectory->setVisible(state); + pythonLabel->setVisible(state); +} +#endif qint32 GeneralPage::saveClicked() @@ -292,6 +322,9 @@ GeneralPage::saveClicked() #ifdef GC_WANT_R appsettings->setValue(GC_R_HOME, rDirectory->text()); #endif +#ifdef GC_WANT_PYTHON + appsettings->setValue(GC_PYTHON_HOME, pythonDirectory->text()); +#endif // Elevation appsettings->setValue(GC_ELEVATION_HYSTERESIS, hystedit->text()); @@ -348,6 +381,29 @@ GeneralPage::browseRDir() if (dir != "") rDirectory->setText(dir); //only overwrite current dir, if a new was selected } #endif +#ifdef GC_WANT_PYTHON +void +GeneralPage::browsePythonDir() +{ + QString currentDir = pythonDirectory->text(); + if (!QDir(currentDir).exists()) currentDir = ""; + QString dir = QFileDialog::getExistingDirectory(this, tr("Python Installation (PYTHONHOME)"), + currentDir, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (dir != "") { + QString pybin, pypath; + + // is it installed there? + bool isgood = PythonEmbed::pythonInstalled(pybin, pypath, dir); + + if (!isgood) { + QMessageBox nope(QMessageBox::Warning, tr("Invalid Folder"), tr("Python does not appear to be installed in that location.\n")); + nope.exec(); + } else { + pythonDirectory->setText(dir); //only overwrite current dir, if a new was selected + } + } +} +#endif void GeneralPage::browseWorkoutDir() diff --git a/src/Gui/Pages.h b/src/Gui/Pages.h index b7c699200..a3fc74115 100644 --- a/src/Gui/Pages.h +++ b/src/Gui/Pages.h @@ -88,6 +88,10 @@ class GeneralPage : public QWidget public slots: void browseWorkoutDir(); void browseAthleteDir(); +#ifdef GC_WANT_PYTHON + void browsePythonDir(); + void embedPythonchanged(int); +#endif #ifdef GC_WANT_R void browseRDir(); void embedRchanged(int); @@ -116,6 +120,11 @@ class GeneralPage : public QWidget QPushButton *workoutBrowseButton; QPushButton *athleteBrowseButton; +#ifdef GC_WANT_PYTHON + QPushButton *pythonBrowseButton; + QLineEdit *pythonDirectory; + QLabel *pythonLabel; +#endif #ifdef GC_WANT_R QPushButton *rBrowseButton; QLineEdit *rDirectory; diff --git a/src/Python/PythonEmbed.cpp b/src/Python/PythonEmbed.cpp index 9637431ad..99eaeadf6 100644 --- a/src/Python/PythonEmbed.cpp +++ b/src/Python/PythonEmbed.cpp @@ -47,41 +47,65 @@ PythonEmbed::~PythonEmbed() { } -bool PythonEmbed::pythonInstalled(QString &pybin, QString &pypath) +bool PythonEmbed::pythonInstalled(QString &pybin, QString &pypath, QString PYTHONHOME) { - // where to check - QString path = QProcessEnvironment::systemEnvironment().value("PATH", ""); - printd("PATH=%s\n", path.toStdString().c_str()); + QString pythonbinary; - // what is is typically installed as ? - QStringList binarynames; - binarynames << "python3" << "python"; + if (PYTHONHOME=="") { - // what we found - QStringList installnames; + // where to check + QString path = QProcessEnvironment::systemEnvironment().value("PATH", ""); + printd("PATH=%s\n", path.toStdString().c_str()); - // lets search - foreach(QString name, binarynames) { - installnames = Utils::searchPath(path, name, true); - if (installnames.count() >0) break; + // what is is typically installed as ? + QStringList binarynames; + binarynames << "python3" << "python"; + + // what we found + QStringList installnames; + + // lets search + foreach(QString name, binarynames) { + installnames = Utils::searchPath(path, name, true); + if (installnames.count() >0) break; + } + + printd("Binary found:%d\n", installnames.count()); + // if we failed, its not installed + if (installnames.count()==0) return false; + + // lets just use the first one we found + pythonbinary = installnames[0]; + pybin=pythonbinary; + + } else { + + // look for python3 or python in PYTHONHOME + QStringList names; names<<"python3"<<"python"; +#ifdef WIN32 + QString ext= QString(".exe"); +#else + QString ext= QString(""); +#endif + foreach(QString name, names) { + QString filename = PYTHONHOME + QDir::separator() + name + ext; + if (QFileInfo(filename).exists() && QFileInfo(filename).isExecutable()) { + pythonbinary=filename; + break; + } + } + // not found give up straight away + if (pythonbinary == "") return false; } - printd("Binary found:%d\n", installnames.count()); - // if we failed, its not installed - if (installnames.count()==0) return false; - - // lets just use the first one we found - QString pythonbinary = installnames[0]; - pybin=pythonbinary; - #ifdef WIN32 - // ugh. QProcess doesn't like spaces or backslashes. POC. - pythonbinary=pythonbinary.replace("\\", "/"); - pythonbinary="\"" + pythonbinary + "\""; + // ugh. QProcess doesn't like spaces or backslashes. POC. + pythonbinary=pythonbinary.replace("\\", "/"); + pythonbinary="\"" + pythonbinary + "\""; #endif - printd("Running: %s\n", pythonbinary.toStdString().c_str()); // get the version and path via an interaction + printd("Running: %s\n", pythonbinary.toStdString().c_str()); QProcess py; py.setProgram(pythonbinary); @@ -154,8 +178,13 @@ PythonEmbed::PythonEmbed(const bool verbose, const bool interactive) : verbose(v threadid=-1; name = QString("GoldenCheetah"); + // config or environment variable + QString PYTHONHOME = appsettings->value(NULL, GC_PYTHON_HOME, "").toString(); + if (PYTHONHOME == "") PYTHONHOME = QProcessEnvironment::systemEnvironment().value("PYTHONHOME", ""); + if (PYTHONHOME !="") printd("PYTHONHOME seteting used: %s\n", PYTHONHOME.toStdString().c_str()); + // is python3 installed? - if (pythonInstalled(pybin, pypath)) { + if (pythonInstalled(pybin, pypath, PYTHONHOME)) { printd("Python is installed: %s\n", pybin.toStdString().c_str()); diff --git a/src/Python/PythonEmbed.h b/src/Python/PythonEmbed.h index 974906dba..b1bbc1199 100644 --- a/src/Python/PythonEmbed.h +++ b/src/Python/PythonEmbed.h @@ -39,7 +39,7 @@ class PythonEmbed { ~PythonEmbed(); // find installed binary and check version and module path - static bool pythonInstalled(QString &pybin, QString &pypath); + static bool pythonInstalled(QString &pybin, QString &pypath, QString PYTHONHOME=QString("")); QString pybin, pypath; // scripts can set a result value