diff --git a/script/download_python_indexer.sh b/script/download_python_indexer.sh index 513882b2..e3b91326 100755 --- a/script/download_python_indexer.sh +++ b/script/download_python_indexer.sh @@ -1,6 +1,6 @@ #!/bin/bash -SOURCETRAIL_PYTHON_INDEXER_VERSION="v0_db24_p1" +SOURCETRAIL_PYTHON_INDEXER_VERSION="v1_db24_p0" # Determine current platform PLATFORM='unknown' diff --git a/src/lib_gui/qt/element/QtLocationPicker.cpp b/src/lib_gui/qt/element/QtLocationPicker.cpp index 2f67767b..0ac713d6 100644 --- a/src/lib_gui/qt/element/QtLocationPicker.cpp +++ b/src/lib_gui/qt/element/QtLocationPicker.cpp @@ -25,6 +25,7 @@ QtLocationPicker::QtLocationPicker(QWidget *parent) m_data = new QtLineEdit(this); m_data->setAttribute(Qt::WA_MacShowFocusRect, 0); m_data->setObjectName("locationField"); + connect(m_data, &QtLineEdit::textChanged, this, &QtLocationPicker::onDataTextChanged); layout->addWidget(m_data); m_button = new QtIconButton( @@ -34,7 +35,7 @@ QtLocationPicker::QtLocationPicker(QWidget *parent) m_button->setIconSize(QSize(16, 16)); m_button->setObjectName("dotsButton"); m_button->setToolTip("pick file"); - connect(m_button, &QPushButton::clicked, this, &QtLocationPicker::handleButtonPress); + connect(m_button, &QPushButton::clicked, this, &QtLocationPicker::onHandleButtonPressed); layout->addWidget(m_button); setLayout(layout); @@ -98,7 +99,7 @@ void QtLocationPicker::changeEvent(QEvent *event) } } -void QtLocationPicker::handleButtonPress() +void QtLocationPicker::onHandleButtonPressed() { FilePath path(m_data->text().toStdWString()); if (!path.empty() && !path.isAbsolute() && !m_relativeRootDirectory.empty()) @@ -124,3 +125,8 @@ void QtLocationPicker::handleButtonPress() emit locationPicked(); } } + +void QtLocationPicker::onDataTextChanged(const QString& text) +{ + emit textChanged(text); +} diff --git a/src/lib_gui/qt/element/QtLocationPicker.h b/src/lib_gui/qt/element/QtLocationPicker.h index 772e9346..21d8837e 100644 --- a/src/lib_gui/qt/element/QtLocationPicker.h +++ b/src/lib_gui/qt/element/QtLocationPicker.h @@ -30,14 +30,15 @@ public: signals: void locationPicked(); + void textChanged(const QString& text); protected: void changeEvent(QEvent *event) override; -private slots: - void handleButtonPress(); - private: + void onHandleButtonPressed(); + void onDataTextChanged(const QString& text); + QPushButton* m_button; QtLineEdit* m_data; diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp index dad11a35..92e5dd8f 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp @@ -6,16 +6,22 @@ #include #include +#include "Application.h" +#include "ApplicationSettings.h" +#include "FileManager.h" +#include "MessageStatus.h" +#include "QtLocationPicker.h" +#include "QtDialogView.h" +#include "QtProjectWizzardContentPaths.h" +#include "ResourcePaths.h" +#include "ScopedFunctor.h" +#include "SonargraphProject.h" #include "SourceGroupCxxCdb.h" #include "SourceGroupCxxCodeblocks.h" #include "SourceGroupCxxSonargraph.h" #include "SourceGroupJavaSonargraph.h" #include "SourceGroupJavaGradle.h" #include "SourceGroupJavaMaven.h" -#include "QtLocationPicker.h" -#include "QtDialogView.h" -#include "QtProjectWizzardContentPaths.h" -#include "ApplicationSettings.h" #include "SourceGroupSettingsCxxCdb.h" #include "SourceGroupSettingsCxxCodeblocks.h" #include "SourceGroupSettingsCxxSonargraph.h" @@ -24,15 +30,11 @@ #include "SourceGroupSettingsJavaSonargraph.h" #include "SourceGroupSettingsPythonEmpty.h" #include "SourceGroupSettingsWithSonargraphProjectPath.h" -#include "FileManager.h" -#include "MessageStatus.h" -#include "SonargraphProject.h" -#include "ScopedFunctor.h" #include "utility.h" +#include "utilityApp.h" #include "utilityFile.h" #include "utilityGradle.h" #include "utilityMaven.h" -#include "Application.h" QtProjectWizzardContentPath::QtProjectWizzardContentPath(QtProjectWizzardWindow* window) : QtProjectWizzardContent(window) @@ -744,6 +746,20 @@ QtProjectWizzardContentPathPythonEnvironment::QtProjectWizzardContentPathPythonE setAllowEmpty(true); } +void QtProjectWizzardContentPathPythonEnvironment::populate(QGridLayout* layout, int& row) +{ + QtProjectWizzardContentPath::populate(layout, row); + connect( + m_picker, &QtLocationPicker::textChanged, + this, &QtProjectWizzardContentPathPythonEnvironment::onTextChanged + ); + + m_resultLabel = new QLabel(); + m_resultLabel->setWordWrap(true); + layout->addWidget(m_resultLabel, row, QtProjectWizzardWindow::BACK_COL); + row++; +} + void QtProjectWizzardContentPathPythonEnvironment::load() { m_picker->setText(QString::fromStdWString(m_settings->getEnvironmentDirectoryPath().wstr())); @@ -754,6 +770,39 @@ void QtProjectWizzardContentPathPythonEnvironment::save() m_settings->setEnvironmentDirectoryPath(FilePath(m_picker->getText().toStdWString())); } +void QtProjectWizzardContentPathPythonEnvironment::onTextChanged(const QString& text) +{ + if (text.isEmpty()) + { + m_resultLabel->clear(); + } + else + { + m_resultLabel->setText("Checking validity of Python environment..."); + std::thread([=]() { + std::pair out = utility::executeProcess( + "\"" + ResourcePaths::getPythonPath().str() + "SourcetrailPythonIndexer\" check-environment " + + "--environment-path \"" + m_settings->makePathExpandedAndAbsolute(FilePath(text.toStdWString())).str() + "\"", + FilePath(), + 5000 + ); + m_onQtThread( + [=]() + { + if (out.first == 0) + { + m_resultLabel->setText(QString::fromStdString(out.second)); + } + else + { + m_resultLabel->setText("An error occurred while checking environment path. Unable to check validity."); + } + } + ); + }).detach(); + } +} + std::shared_ptr QtProjectWizzardContentPathPythonEnvironment::getSourceGroupSettings() { return m_settings; diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.h index 543ad006..4948e3e7 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.h @@ -4,6 +4,7 @@ #include #include "QtProjectWizzardContent.h" +#include "QtThreadedFunctor.h" #include "SingleValueCache.h" class QCheckBox; @@ -245,13 +246,17 @@ public: QtProjectWizzardContentPathPythonEnvironment(std::shared_ptr settings, QtProjectWizzardWindow* window); // QtProjectWizzardContent implementation + void populate(QGridLayout* layout, int& row) override; void load() override; void save() override; private: + void onTextChanged(const QString& text); std::shared_ptr getSourceGroupSettings() override; std::shared_ptr m_settings; + QtThreadedLambdaFunctor m_onQtThread; + QLabel* m_resultLabel; }; #endif // QT_PROJECT_WIZZARD_CONTENT_PATH_H diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentSelect.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentSelect.cpp index 3c844cb0..e24d413f 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentSelect.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentSelect.cpp @@ -26,7 +26,7 @@ void QtProjectWizzardContentSelect::populate(QGridLayout* layout, int& row) { std::string pythonIndexerVersion = " "; { - std::string str = utility::executeProcess("\"" + ResourcePaths::getPythonPath().str() + "SourcetrailPythonIndexer\" --version", FilePath(), 5000); + std::string str = utility::executeProcess("\"" + ResourcePaths::getPythonPath().str() + "SourcetrailPythonIndexer\" --version", FilePath(), 5000).second; std::regex regex("v\\d*\\.db\\d*\\.p\\d*"); // "\\d" matches any digit; "\\." matches the "." character std::smatch matches; std::regex_search(str, matches, regex); diff --git a/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp b/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp index d1acfaec..3c4e2c6a 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp @@ -23,7 +23,7 @@ std::vector CxxVs15HeaderPathDetector::getPaths() const { const std::string command = "\"" + expandedPaths[0].str() + "\" -latest -property installationPath"; const std::string command2 = "\"C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe\""; - const std::string output = utility::executeProcess(command, FilePath(), 10000); + const std::string output = utility::executeProcess(command, FilePath(), 10000).second; const FilePath vsInstallPath(output); if (vsInstallPath.exists()) diff --git a/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.cpp b/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.cpp index d2eb0f61..aba3557a 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/utilityCxxHeaderDetection.cpp @@ -12,7 +12,7 @@ namespace utility std::vector getCxxHeaderPaths(const std::string& compilerName) { std::string command = compilerName + " -x c++ -v -E /dev/null"; - std::string clangOutput = utility::executeProcess(command.c_str()); + std::string clangOutput = utility::executeProcess(command.c_str()).second; std::string standardHeaders = utility::substrBetween(clangOutput, "#include <...> search starts here:\n","\nEnd of search list"); std::vector paths; diff --git a/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorLinux.cpp b/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorLinux.cpp index 64132e8d..25d0e22f 100644 --- a/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorLinux.cpp +++ b/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorLinux.cpp @@ -19,7 +19,7 @@ JavaPathDetectorLinux::JavaPathDetectorLinux(const std::string javaVersion) FilePath JavaPathDetectorLinux::getJavaInPath() const { std::string command = "which java"; - std::string output = utility::executeProcess(command.c_str()); + std::string output = utility::executeProcess(command.c_str()).second; if (!output.empty()) { @@ -38,7 +38,7 @@ FilePath JavaPathDetectorLinux::getJavaInPath() const FilePath JavaPathDetectorLinux::readLink(const FilePath& path) const { std::string command = "readlink -f " + path.str(); - FilePath javaPath( utility::executeProcess(command.c_str())); + FilePath javaPath( utility::executeProcess(command.c_str()).second); if (!javaPath.empty()) { return javaPath; @@ -77,7 +77,7 @@ FilePath JavaPathDetectorLinux::getJavaInJavaHome() const bool JavaPathDetectorLinux::checkVersion(const FilePath& path) const { std::string command = path.str() + " -version"; - std::string output = utility::executeProcess(command.c_str()); + std::string output = utility::executeProcess(command.c_str()).second; return output.find(m_javaVersion) != std::string::npos; } diff --git a/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorMac.cpp b/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorMac.cpp index 9cc5dc20..b3ca6d78 100644 --- a/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorMac.cpp +++ b/src/lib_gui/utility/path_detector/java_runtime/JavaPathDetectorMac.cpp @@ -15,7 +15,7 @@ std::vector JavaPathDetectorMac::getPaths() const FilePath javaPath; std::string command = "/usr/libexec/java_home"; - std::string output = utility::executeProcess(command.c_str()); + std::string output = utility::executeProcess(command.c_str()).second; if (!output.empty()) { diff --git a/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorUnix.cpp b/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorUnix.cpp index 72f2740a..0265b70a 100644 --- a/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorUnix.cpp +++ b/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorUnix.cpp @@ -11,7 +11,7 @@ MavenPathDetectorUnix::MavenPathDetectorUnix() std::vector MavenPathDetectorUnix::getPaths() const { std::string command = "which mvn"; - FilePath mavenPath(utility::executeProcess(command.c_str())); + FilePath mavenPath(utility::executeProcess(command.c_str()).second); std::vector paths; if (mavenPath.exists()) diff --git a/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorWindows.cpp b/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorWindows.cpp index fd79eb97..6abccfee 100644 --- a/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorWindows.cpp +++ b/src/lib_gui/utility/path_detector/maven_executable/MavenPathDetectorWindows.cpp @@ -11,7 +11,7 @@ MavenPathDetectorWindows::MavenPathDetectorWindows() std::vector MavenPathDetectorWindows::getPaths() const { std::string command = "cmd /c where mvn.cmd && exit"; - FilePath mavenPath(utility::executeProcess(command.c_str())); + FilePath mavenPath(utility::executeProcess(command.c_str()).second); std::vector paths; if (mavenPath.exists()) diff --git a/src/lib_gui/utility/utilityApp.cpp b/src/lib_gui/utility/utilityApp.cpp index ab15452d..9448413f 100644 --- a/src/lib_gui/utility/utilityApp.cpp +++ b/src/lib_gui/utility/utilityApp.cpp @@ -52,7 +52,7 @@ namespace utility std::set s_runningProcesses; } -std::string utility::executeProcess(const std::string& command, const FilePath& workingDirectory, const int timeout) +std::pair utility::executeProcess(const std::string& command, const FilePath& workingDirectory, const int timeout) { QProcess process; process.setProcessChannelMode(QProcess::MergedChannels); @@ -81,11 +81,11 @@ std::string utility::executeProcess(const std::string& command, const FilePath& // QProcess::ProcessError error = process.error(); - std::string processoutput = process.readAll().toStdString(); + const std::string processoutput = process.readAll().toStdString(); + const int exitCode = process.exitCode(); process.close(); - processoutput = utility::trim(processoutput); - return processoutput; + return std::make_pair(exitCode, utility::trim(processoutput)); } std::string utility::executeProcessUntilNoOutput(const std::string& command, const FilePath& workingDirectory, const int waitTime) diff --git a/src/lib_gui/utility/utilityApp.h b/src/lib_gui/utility/utilityApp.h index 667146c4..a553bf95 100644 --- a/src/lib_gui/utility/utilityApp.h +++ b/src/lib_gui/utility/utilityApp.h @@ -12,7 +12,7 @@ class License; namespace utility { - std::string executeProcess(const std::string& command, const FilePath& workingDirectory = FilePath(), const int timeout = 30000); + std::pair executeProcess(const std::string& command, const FilePath& workingDirectory = FilePath(), const int timeout = 30000); std::string executeProcessUntilNoOutput(const std::string& command, const FilePath& workingDirectory, int waitTime = 10000); int executeProcessAndGetExitCode( const std::wstring& commandPath, diff --git a/src/lib_python/project/SourceGroupPythonEmpty.cpp b/src/lib_python/project/SourceGroupPythonEmpty.cpp index 34423733..c1eecd1e 100644 --- a/src/lib_python/project/SourceGroupPythonEmpty.cpp +++ b/src/lib_python/project/SourceGroupPythonEmpty.cpp @@ -49,7 +49,7 @@ std::vector> SourceGroupPythonEmpty::getIndexerC if (!m_settings->getEnvironmentDirectoryPath().empty()) { - args += L" --environment-directory-path=" + m_settings->getEnvironmentDirectoryPathExpandedAndAbsolute().wstr(); + args += L" --environment-path=" + m_settings->getEnvironmentDirectoryPathExpandedAndAbsolute().wstr(); } if (ApplicationSettings::getInstance()->getVerboseIndexerLoggingEnabled()) @@ -64,7 +64,7 @@ std::vector> SourceGroupPythonEmpty::getIndexerC { indexerCommands.push_back(std::make_shared( INDEXER_COMMAND_PYTHON, - L"\"" + ResourcePaths::getPythonPath().wstr() + L"SourcetrailPythonIndexer\"" + args, + L"\"" + ResourcePaths::getPythonPath().wstr() + L"SourcetrailPythonIndexer\" index" + args, m_settings->getProjectSettings()->getProjectFilePath(), m_settings->getProjectSettings()->getTempDBFilePath(), std::to_wstring(SqliteIndexStorage::getStorageVersion()),