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;