Browse Source

Improved Python detection (Win32)

Propose to download and install python if missing (Win32)
adaptive-webui-19844
Christophe Dumez 15 years ago
parent
commit
a3041b7f9f
  1. 30
      src/preferences.h
  2. 102
      src/searchengine.cpp
  3. 8
      src/searchengine.h

30
src/preferences.h

@ -990,14 +990,30 @@ public:
} }
#ifdef Q_WS_WIN #ifdef Q_WS_WIN
static void setPythonPath(QString path) {
QSettings settings("qBittorrent", "qBittorrent");
settings.setValue(QString::fromUtf8("Preferences/Win32/PythonPath"), path);
}
static QString getPythonPath() { static QString getPythonPath() {
QSettings settings("qBittorrent", "qBittorrent"); QSettings reg_python("HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore", QSettings::NativeFormat);
return settings.value(QString::fromUtf8("Preferences/Win32/PythonPath"), "").toString(); QStringList versions = reg_python.childGroups();
qDebug("Python versions nb: %d", versions.size());
versions = versions.filter(QRegExp("2\\..*"));
versions.sort();
while(!versions.empty()) {
const QString version = versions.takeLast();
qDebug("Detected possible Python v%s location", qPrintable(version));
QString path = reg_python.value(version+"/InstallPath/Default", "").toString().replace("/", "\\");
if(!path.isEmpty() && QDir(path).exists("python.exe")) {
qDebug("Found python.exe at %s", qPrintable(path));
return path;
}
}
if(QFile::exists("C:/Python26/python.exe")) {
reg_python.setValue("2.6/InstallPath/Default", "C:\\Python26");
return "C:\\Python26";
}
if(QFile::exists("C:/Python25/python.exe")) {
reg_python.setValue("2.5/InstallPath/Default", "C:\\Python26");
return "C:\\Python25";
}
return QString::null;
} }
static bool neverCheckFileAssoc() { static bool neverCheckFileAssoc() {

102
src/searchengine.cpp

@ -79,11 +79,10 @@ SearchEngine::SearchEngine(GUI *parent, Bittorrent *BTSession) : QWidget(parent)
search_stopped = false; search_stopped = false;
// Creating Search Process // Creating Search Process
#ifdef Q_WS_WIN #ifdef Q_WS_WIN
checkForPythonExe(); has_python = addPythonPathToEnv();
#endif #endif
searchProcess = new QProcess(this); searchProcess = new QProcess(this);
QStringList env = QProcess::systemEnvironment(); searchProcess->setEnvironment(QProcess::systemEnvironment());
searchProcess->setEnvironment(env);
connect(searchProcess, SIGNAL(started()), this, SLOT(searchStarted())); connect(searchProcess, SIGNAL(started()), this, SLOT(searchStarted()));
connect(searchProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readSearchOutput())); connect(searchProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readSearchOutput()));
connect(searchProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(searchFinished(int,QProcess::ExitStatus))); connect(searchProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(searchFinished(int,QProcess::ExitStatus)));
@ -111,46 +110,9 @@ void SearchEngine::fillCatCombobox() {
} }
#ifdef Q_WS_WIN #ifdef Q_WS_WIN
void SearchEngine::checkForPythonExe() { bool SearchEngine::addPythonPathToEnv() {
QString python_path = Preferences::getPythonPath(); QString python_path = Preferences::getPythonPath();
if(python_path.isEmpty() || !QFile::exists(python_path+QDir::separator()+"python.exe")) { if(!python_path.isEmpty()) {
// Attempt to detect python in standard location
QStringList filters;
filters << "Python25" << "Python26";
QStringList python_folders = QDir::root().entryList(filters, QDir::Dirs, QDir::Name);
if(!python_folders.isEmpty()) {
python_path = QDir::root().absoluteFilePath(python_folders.last());
qDebug("Detected python folder at %s", qPrintable(python_path));
} else {
filters.clear();
filters << "Python*";
python_folders = QDir::root().entryList(filters, QDir::Dirs, QDir::Name);
if(!python_folders.isEmpty()) {
python_path = QDir::root().absoluteFilePath(python_folders.last());
qDebug("Detected python folder at %s", qPrintable(python_path));
} else {
qDebug("Failed to detect Python folder");
}
}
}
if(python_path.isEmpty() || !QFile::exists(python_path+QDir::separator()+"python.exe")) {
QMessageBox::warning(0, tr("Failed to locate the Python interpreter"), tr("The Python interpreter was not found.\nqBittorrent will now ask you to point to its correct location."));
QString python_exe_path = QFileDialog::getOpenFileName(0, tr("Please point to its location on your hard disk."),
QDir::root().absolutePath(), tr("Python executable (python.exe)"));
if(python_exe_path.isEmpty() || !QFile::exists(python_exe_path)) {
QMessageBox::warning(0, tr("No Python interpreter"), tr("The Python interpreter is missing. qBittorrent search engine will not work."));
return;
}
qDebug("Python exe path is: %s", qPrintable(python_exe_path));
QStringList tmp_list = python_exe_path.split(QDir::separator());
if(tmp_list.size() == 1)
tmp_list = tmp_list.first().split("/");
tmp_list.removeLast();
python_path = tmp_list.join(QDir::separator());
qDebug("New Python path is: %s", qPrintable(python_path));
// Save python path
Preferences::setPythonPath(python_path);
}
// Add it to PATH envvar // Add it to PATH envvar
QString path_envar = QString::fromLocal8Bit(getenv("PATH")); QString path_envar = QString::fromLocal8Bit(getenv("PATH"));
if(path_envar.isNull()) { if(path_envar.isNull()) {
@ -160,7 +122,51 @@ void SearchEngine::checkForPythonExe() {
qDebug("New PATH envvar is: %s", qPrintable(path_envar)); qDebug("New PATH envvar is: %s", qPrintable(path_envar));
QString envar = "PATH="+path_envar; QString envar = "PATH="+path_envar;
putenv(envar.toLocal8Bit().data()); putenv(envar.toLocal8Bit().data());
return true;
}
return false;
} }
void SearchEngine::installPython() {
setCursor(QCursor(Qt::WaitCursor));
// Download python
downloadThread *pydownloader = new downloadThread(this);
connect(pydownloader, SIGNAL(downloadFinished(QString,QString)), this, SLOT(pythonDownloadSuccess(QString,QString)));
connect(pydownloader, SIGNAL(downloadFailure(QString,QString)), this, SLOT(pythonDownloadFailure(QString,QString)));
pydownloader->downloadUrl("http://python.org/ftp/python/2.6.5/python-2.6.5.msi");
}
void SearchEngine::pythonDownloadSuccess(QString url, QString file_path) {
setCursor(QCursor(Qt::ArrowCursor));
Q_UNUSED(url);
QFile::rename(file_path, file_path+".msi");
QProcess installer;
qDebug("Launching Python installer in passive mode...");
installer.start("msiexec.exe /passive /i "+file_path.replace("/", "\\")+".msi");
// Wait for setup to complete
installer.waitForFinished();
qDebug("Installer stdout: %s", installer.readAllStandardOutput().data());
qDebug("Installer stderr: %s", installer.readAllStandardError().data());
qDebug("Setup should be complete!");
// Reload search engine
has_python = addPythonPathToEnv();
if(has_python) {
supported_engines->update();
// Launch the search again
on_search_button_clicked();
}
// Delete temp file
QFile::remove(file_path+".msi");
}
void SearchEngine::pythonDownloadFailure(QString url, QString error) {
Q_UNUSED(url);
setCursor(QCursor(Qt::ArrowCursor));
QMessageBox::warning(this, tr("Download error"), tr("Python setup could not be downloaded, reason: %1.\nPlease install it manually.").arg(error));
}
#endif #endif
QString SearchEngine::selectedCategory() const { QString SearchEngine::selectedCategory() const {
@ -269,6 +275,17 @@ void SearchEngine::searchTextEdited(QString) {
// Function called when we click on search button // Function called when we click on search button
void SearchEngine::on_search_button_clicked(){ void SearchEngine::on_search_button_clicked(){
#ifdef Q_WS_WIN
if(!has_python) {
if(QMessageBox::question(this, tr("Missing Python Interpreter"),
tr("Python 2.x is required to use the search engine but it does not seem to be installed.\nDo you want to install it now?"),
QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
// Download and Install Python
installPython();
}
return;
}
#endif
if(searchProcess->state() != QProcess::NotRunning){ if(searchProcess->state() != QProcess::NotRunning){
searchProcess->terminate(); searchProcess->terminate();
search_stopped = true; search_stopped = true;
@ -381,6 +398,7 @@ void SearchEngine::downloadTorrent(QString engine_url, QString torrent_url) {
parent->downloadFromURLList(urls); parent->downloadFromURLList(urls);
} else { } else {
QProcess *downloadProcess = new QProcess(this); QProcess *downloadProcess = new QProcess(this);
downloadProcess->setEnvironment(QProcess::systemEnvironment());
connect(downloadProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(downloadFinished(int,QProcess::ExitStatus))); connect(downloadProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(downloadFinished(int,QProcess::ExitStatus)));
downloaders << downloadProcess; downloaders << downloadProcess;
QStringList params; QStringList params;

8
src/searchengine.h

@ -70,6 +70,9 @@ private:
QList<QPointer<SearchTab> > all_tab; // To store all tabs QList<QPointer<SearchTab> > all_tab; // To store all tabs
const SearchCategories full_cat_names; const SearchCategories full_cat_names;
GUI *parent; GUI *parent;
#ifdef Q_WS_WIN
bool has_python;
#endif
public: public:
SearchEngine(GUI *parent, Bittorrent *BTSession); SearchEngine(GUI *parent, Bittorrent *BTSession);
@ -127,7 +130,10 @@ protected slots:
void fillCatCombobox(); void fillCatCombobox();
void searchTextEdited(QString); void searchTextEdited(QString);
#ifdef Q_WS_WIN #ifdef Q_WS_WIN
void checkForPythonExe(); bool addPythonPathToEnv();
void installPython();
void pythonDownloadSuccess(QString url, QString file_path);
void pythonDownloadFailure(QString url, QString error);
#endif #endif
}; };

Loading…
Cancel
Save