diff --git a/gui/checkthread.cpp b/gui/checkthread.cpp index 1fced9549..84f35e58c 100644 --- a/gui/checkthread.cpp +++ b/gui/checkthread.cpp @@ -267,12 +267,32 @@ void CheckThread::runAddons(const QString &addonPath, const ImportProject::FileS mCppcheck.settings().buildDir = buildDir; } - QString cmd = "python " + a + ' ' + dumpFile; - qDebug() << cmd; + const QString python = mPythonPath.isEmpty() ? QString("python") : mPythonPath; + QStringList args; + args << a << dumpFile; + qDebug() << python << args; + QProcess process; - process.start(cmd); + if (!mPythonPath.isEmpty()) { + QStringList env(QProcess::systemEnvironment()); + for (int i = 0; i < env.size(); ++i) { + if (env[i].startsWith("PYTHONHOME=")) { + env.removeAt(i); + process.setEnvironment(env); + break; + } + } + } + process.start(python, args); process.waitForFinished(); - parseAddonErrors(process.readAllStandardError(), addon); + const QString errout(process.readAllStandardError()); + QFile f(dumpFile + '-' + addon + "-results"); + if (f.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&f); + out << errout; + f.close(); + } + parseAddonErrors(errout, addon); } } } @@ -289,6 +309,8 @@ QString CheckThread::getAddonPath() const return mDataDir; else if (QDir(mDataDir + "/addons").exists()) return mDataDir + "/addons"; + else if (QDir(mDataDir + "/../addons").exists()) + return mDataDir + "/../addons"; else if (mDataDir.endsWith("/cfg")) { if (QDir(mDataDir.mid(0,mDataDir.size()-3) + "addons").exists()) return mDataDir.mid(0,mDataDir.size()-3) + "addons"; diff --git a/gui/checkthread.h b/gui/checkthread.h index 367b3cec4..c453031a7 100644 --- a/gui/checkthread.h +++ b/gui/checkthread.h @@ -56,6 +56,10 @@ public: mAddons = addons; } + void setPythonPath(const QString &p) { + mPythonPath = p; + } + void setDataDir(const QString &dataDir) { mDataDir = dataDir; } @@ -128,6 +132,7 @@ private: QStringList mFiles; bool mAnalyseWholeProgram; QStringList mAddons; + QString mPythonPath; QString mDataDir; QString mClangPath; QStringList mClangIncludePaths; diff --git a/gui/common.h b/gui/common.h index 2be2496e1..7d57114ba 100644 --- a/gui/common.h +++ b/gui/common.h @@ -80,6 +80,7 @@ #define SETTINGS_APPLICATION_DEFAULT "Default Application" #define SETTINGS_LANGUAGE "Application language" #define SETTINGS_GLOBAL_INCLUDE_PATHS "Global include paths" +#define SETTINGS_PYTHON_PATH "Python path" #define SETTINGS_CLANG_PATH "Clang path" #define SETTINGS_VS_INCLUDE_PATHS "VS include paths" #define SETTINGS_INLINE_SUPPRESSIONS "Inline suppressions" diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 1b9397c16..489ecc1a3 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -444,6 +444,7 @@ void MainWindow::doAnalyzeProject(ImportProject p) //mThread->SetanalyzeProject(true); if (mProjectFile) { mThread->setAddons(mProjectFile->getAddons()); + mThread->setPythonPath(mSettings->value(SETTINGS_PYTHON_PATH).toString()); QString clangHeaders = mSettings->value(SETTINGS_VS_INCLUDE_PATHS).toString(); mThread->setClangIncludePaths(clangHeaders.split(";")); #ifdef Q_OS_WIN diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp index d08cdbdcb..7b27e6ddf 100644 --- a/gui/resultstree.cpp +++ b/gui/resultstree.cpp @@ -961,7 +961,7 @@ void ResultsTree::suppressSelectedIds() // delete all errors with selected message Ids for (int i = 0; i < mModel.rowCount(); i++) { QStandardItem * const file = mModel.item(i, 0); - for (int j = 0; j < file->rowCount(); ) { + for (int j = 0; j < file->rowCount();) { QStandardItem *errorItem = file->child(j, 0); QVariantMap userdata = errorItem->data().toMap(); if (selectedIds.contains(userdata["id"].toString())) { diff --git a/gui/settings.ui b/gui/settings.ui index a90cafa24..fa4d342ee 100644 --- a/gui/settings.ui +++ b/gui/settings.ui @@ -66,7 +66,7 @@ - 009; + 009 @@ -282,6 +282,45 @@ + + + Addons + + + + + + Python binary (leave this empty to use python in the PATH) + + + + + + + + + ... + + + + + + + + + + Qt::Vertical + + + + 20 + 168 + + + + + + Clang diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index 061595090..fb3588b2d 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -53,6 +53,7 @@ SettingsDialog::SettingsDialog(ApplicationList *list, mUI.mEnableInconclusive->setCheckState(boolToCheckState(settings.value(SETTINGS_INCONCLUSIVE_ERRORS, false).toBool())); mUI.mShowStatistics->setCheckState(boolToCheckState(settings.value(SETTINGS_SHOW_STATISTICS, false).toBool())); mUI.mShowErrorId->setCheckState(boolToCheckState(settings.value(SETTINGS_SHOW_ERROR_ID, false).toBool())); + mUI.mEditPythonPath->setText(settings.value(SETTINGS_PYTHON_PATH, QString()).toString()); #ifdef Q_OS_WIN //mUI.mTabClang->setVisible(true); @@ -75,6 +76,8 @@ SettingsDialog::SettingsDialog(ApplicationList *list, connect(mUI.mListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(editApplication())); + connect(mUI.mBtnBrowsePythonPath, &QPushButton::clicked, this, &SettingsDialog::browsePythonPath); + mUI.mListWidget->setSortingEnabled(false); populateApplicationList(); @@ -157,6 +160,7 @@ void SettingsDialog::saveSettingValues() const saveCheckboxValue(&settings, mUI.mEnableInconclusive, SETTINGS_INCONCLUSIVE_ERRORS); saveCheckboxValue(&settings, mUI.mShowStatistics, SETTINGS_SHOW_STATISTICS); saveCheckboxValue(&settings, mUI.mShowErrorId, SETTINGS_SHOW_ERROR_ID); + settings.setValue(SETTINGS_PYTHON_PATH, mUI.mEditPythonPath->text()); #ifdef Q_OS_WIN settings.setValue(SETTINGS_CLANG_PATH, mUI.mEditClangPath->text()); @@ -295,6 +299,13 @@ bool SettingsDialog::showInconclusive() const return checkStateToBool(mUI.mEnableInconclusive->checkState()); } +void SettingsDialog::browsePythonPath() +{ + QString fileName = QFileDialog::getOpenFileName(this, tr("Select python binary"), QDir::rootPath()); + if (fileName.contains("python", Qt::CaseInsensitive)) + mUI.mEditPythonPath->setText(fileName); +} + void SettingsDialog::browseClangPath() { QString selectedDir = QFileDialog::getExistingDirectory(this, diff --git a/gui/settingsdialog.h b/gui/settingsdialog.h index b49ab6c97..24f60188d 100644 --- a/gui/settingsdialog.h +++ b/gui/settingsdialog.h @@ -124,6 +124,9 @@ protected slots: */ void defaultApplication(); + /** @brief Slot for browsing for the python binary */ + void browsePythonPath(); + /** @brief Slot for browsing for the clang binary */ void browseClangPath(); protected: diff --git a/gui/threadhandler.cpp b/gui/threadhandler.cpp index 49df67002..58ad80e42 100644 --- a/gui/threadhandler.cpp +++ b/gui/threadhandler.cpp @@ -94,6 +94,7 @@ void ThreadHandler::check(const Settings &settings) for (int i = 0; i < mRunningThreadCount; i++) { mThreads[i]->setAddons(mAddons); + mThreads[i]->setPythonPath(mPythonPath); mThreads[i]->setSuppressions(mSuppressions); mThreads[i]->setClangPath(mClangPath); mThreads[i]->setClangIncludePaths(mClangIncludePaths); diff --git a/gui/threadhandler.h b/gui/threadhandler.h index 797e4edc3..88cf7ac6a 100644 --- a/gui/threadhandler.h +++ b/gui/threadhandler.h @@ -79,6 +79,10 @@ public: mSuppressions = s; } + void setPythonPath(const QString &p) { + mPythonPath = p; + } + void setClangPath(const QString &p) { mClangPath = p; } @@ -255,6 +259,7 @@ protected: QStringList mAddons; QStringList mSuppressions; + QString mPythonPath; QString mClangPath; QStringList mClangIncludePaths;