logic: Added SourceGroupCustomCommand to use with SourcetrailDB binaries

* Added new Source Group type SourceGroupCustomCommand to UI and ProjectSettings
* The Source Group executes a specified command on every source file
* The variables $SOURCE_PATH, $PROJECT_PATH, $DB_PATH, $STORAGE_VERSION can be passed
* The commands are executed after all other source groups finished indexing
* The command is executed with working directory set to project directory
* Errors during command execution are shown as status update and in the Status View
* SourceGroupCustomCommand cannot be partially cleared, when one file needs clearing the project must be fully re-indexed
This commit is contained in:
Eberhard Graether
2018-12-11 14:05:26 +01:00
parent 21d947ed6c
commit 6d5a3c047d
101 changed files with 1108 additions and 235 deletions
+2
View File
@@ -203,6 +203,8 @@ add_files(
qt/window/project_wizzard/QtProjectWizzardContentCrossCompilationOptions.h
qt/window/project_wizzard/QtProjectWizzardContentCStandard.cpp
qt/window/project_wizzard/QtProjectWizzardContentCStandard.h
qt/window/project_wizzard/QtProjectWizzardContentCustomCommand.cpp
qt/window/project_wizzard/QtProjectWizzardContentCustomCommand.h
qt/window/project_wizzard/QtProjectWizzardContentExtensions.cpp
qt/window/project_wizzard/QtProjectWizzardContentExtensions.h
qt/window/project_wizzard/QtProjectWizzardContentFlags.cpp
+17
View File
@@ -266,6 +266,23 @@ void QtDialogView::updateIndexingDialog(
);
}
void QtDialogView::updateCustomIndexingDialog(
size_t startedFileCount, size_t finishedFileCount, size_t totalFileCount, const std::vector<FilePath>& sourcePaths)
{
updateIndexingDialog(startedFileCount, finishedFileCount, totalFileCount, sourcePaths);
m_onQtThread(
[=]()
{
QtIndexingDialog* window = dynamic_cast<QtIndexingDialog*>(m_windowStack.getTopWindow());
if (window && window->getType() == QtIndexingDialog::DIALOG_INDEXING)
{
window->updateTitle("Executing Commands");
}
}
);
}
DatabasePolicy QtDialogView::finishedIndexingDialog(
size_t indexedFileCount, size_t totalIndexedFileCount, size_t completedFileCount, size_t totalFileCount,
float time, ErrorCountInfo errorInfo, bool interrupted)
+2
View File
@@ -42,6 +42,8 @@ public:
std::function<void(const RefreshInfo& info)> onStartIndexing, std::function<void()> onCancelIndexing) override;
void updateIndexingDialog(
size_t startedFileCount, size_t finishedFileCount, size_t totalFileCount, const std::vector<FilePath>& sourcePaths) override;
void updateCustomIndexingDialog(
size_t startedFileCount, size_t finishedFileCount, size_t totalFileCount, const std::vector<FilePath>& sourcePaths) override;
DatabasePolicy finishedIndexingDialog(
size_t indexedFileCount, size_t totalIndexedFileCount, size_t completedFileCount, size_t totalFileCount,
float time, ErrorCountInfo errorInfo, bool interrupted) override;
+5
View File
@@ -124,6 +124,11 @@ void QtStatusView::addStatus(const std::vector<Status>& status)
QString statusType = (s.type == StatusType::STATUS_ERROR ? "ERROR" : "INFO");
m_model->setItem(rowNumber, STATUSVIEW_COLUMN::TYPE, new QStandardItem(statusType));
m_model->setItem(rowNumber, STATUSVIEW_COLUMN::STATUS, new QStandardItem(QString::fromStdWString(s.message)));
if (s.type == StatusType::STATUS_ERROR)
{
m_model->item(rowNumber, STATUSVIEW_COLUMN::TYPE)->setForeground(QBrush(Qt::red));
}
}
m_table->updateRows();
@@ -294,6 +294,14 @@ void QtIndexingDialog::setupProgress(bool hideable)
finishSetup();
}
void QtIndexingDialog::updateTitle(const QString& title)
{
if (m_title)
{
m_title->setText(title);
}
}
void QtIndexingDialog::updateMessage(const QString& message)
{
if (m_messageLabel)
+1
View File
@@ -48,6 +48,7 @@ public:
void setupUnknownProgress(bool hideable);
void setupProgress(bool hideable);
void updateTitle(const QString& title);
void updateMessage(const QString& message);
std::wstring getMessage() const;
void updateProgress(size_t progress);
@@ -11,6 +11,7 @@
#include "QtProjectWizzardContentCppStandard.h"
#include "QtProjectWizzardContentCrossCompilationOptions.h"
#include "QtProjectWizzardContentCStandard.h"
#include "QtProjectWizzardContentCustomCommand.h"
#include "QtProjectWizzardContentExtensions.h"
#include "QtProjectWizzardContentFlags.h"
#include "QtProjectWizzardContentJavaStandard.h"
@@ -25,6 +26,7 @@
#include "QtSourceGroupWizzardPage.h"
#include "SourceGroupSettingsCEmpty.h"
#include "SourceGroupSettingsCppEmpty.h"
#include "SourceGroupSettingsCustomCommand.h"
#include "SourceGroupSettingsCxxCdb.h"
#include "SourceGroupSettingsCxxCdbVs.h"
#include "SourceGroupSettingsCxxCodeblocks.h"
@@ -116,7 +118,7 @@ namespace
{
QtSourceGroupWizzardPage<SourceGroupSettingsCEmpty> page("Framework Search Paths");
page.addContentCreatorWithSettings<QtProjectWizzardContentPathsFrameworkSearch>(WIZZARD_CONTENT_CONTEXT_ALL);
page.addContentCreatorSimple<QtProjectWizzardContentPathsFrameworkSearchGlobal>(WIZZARD_CONTENT_CONTEXT_ALL);
page.addContentCreatorSimple<QtProjectWizzardContentPathsFrameworkSearchGlobal>(WIZZARD_CONTENT_CONTEXT_ALL);
pages.push_back(page);
}
{
@@ -148,7 +150,7 @@ namespace
{
QtSourceGroupWizzardPage<SourceGroupSettingsCppEmpty> page("Include Paths");
page.addContentCreatorWithSettings<QtProjectWizzardContentPathsHeaderSearch>(WIZZARD_CONTENT_CONTEXT_ALL);
page.addContentCreatorSimple<QtProjectWizzardContentPathsHeaderSearchGlobal>(WIZZARD_CONTENT_CONTEXT_ALL);
page.addContentCreatorSimple<QtProjectWizzardContentPathsHeaderSearchGlobal>(WIZZARD_CONTENT_CONTEXT_ALL);
pages.push_back(page);
}
if (utility::getOsType() == OS_MAC)
@@ -402,6 +404,21 @@ namespace
return pages;
}
template<>
std::vector<QtSourceGroupWizzardPage<SourceGroupSettingsCustomCommand>> getSourceGroupWizzardPages<SourceGroupSettingsCustomCommand>()
{
std::vector<QtSourceGroupWizzardPage<SourceGroupSettingsCustomCommand>> pages;
{
QtSourceGroupWizzardPage<SourceGroupSettingsCustomCommand> page("Indexed Paths");
page.addContentCreatorWithSettings<QtProjectWizzardContentCustomCommand>(WIZZARD_CONTENT_CONTEXT_ALL);
page.addContentCreatorWithSettings<QtProjectWizzardContentPathsSource>(WIZZARD_CONTENT_CONTEXT_ALL);
page.addContentCreatorWithSettings<QtProjectWizzardContentPathsExclude>(WIZZARD_CONTENT_CONTEXT_ALL);
page.addContentCreatorWithSettings<QtProjectWizzardContentExtensions>(WIZZARD_CONTENT_CONTEXT_ALL);
pages.push_back(page);
}
return pages;
}
template <typename SettingsType>
void fillSummary(QtProjectWizzardContentGroup* summary, std::shared_ptr<SettingsType> settings, QtProjectWizzardWindow* window)
{
@@ -476,7 +493,7 @@ void QtProjectWizzard::newProjectFromCDB(const FilePath& filePath)
std::make_shared<SourceGroupSettingsCxxCdbVs>(utility::getUuidString(), m_projectSettings.get());
sourceGroupSettings->setCompilationDatabasePath(filePath);
executeSoureGroupSetup<SourceGroupSettingsCxxCdbVs>(sourceGroupSettings);
executeSourceGroupSetup<SourceGroupSettingsCxxCdbVs>(sourceGroupSettings);
}
void QtProjectWizzard::editProject(const FilePath& settingsPath)
@@ -633,7 +650,7 @@ void QtProjectWizzard::handlePrevious()
}
template <typename SettingsType>
void QtProjectWizzard::executeSoureGroupSetup(std::shared_ptr<SettingsType> settings)
void QtProjectWizzard::executeSourceGroupSetup(std::shared_ptr<SettingsType> settings)
{
std::shared_ptr<QtSourceGroupWizzard<SettingsType>> wizzard = std::make_shared<QtSourceGroupWizzard<SettingsType>>(
settings,
@@ -825,6 +842,10 @@ void QtProjectWizzard::selectedSourceGroupChanged(int index)
{
fillSummary(summary, settings, this);
}
else if (std::shared_ptr<SourceGroupSettingsCustomCommand> settings = std::dynamic_pointer_cast<SourceGroupSettingsCustomCommand>(group))
{
fillSummary(summary, settings, this);
}
setContent(summary);
@@ -1003,46 +1024,46 @@ void QtProjectWizzard::selectedProjectType(SourceGroupType sourceGroupType)
{
std::shared_ptr<SourceGroupSettingsCEmpty> settings = std::make_shared<SourceGroupSettingsCEmpty>(sourceGroupId, m_projectSettings.get());
addMsvcCompatibilityFlagsOnDemand(settings);
executeSoureGroupSetup<SourceGroupSettingsCEmpty>(settings);
executeSourceGroupSetup<SourceGroupSettingsCEmpty>(settings);
}
break;
case SOURCE_GROUP_CPP_EMPTY:
{
std::shared_ptr<SourceGroupSettingsCppEmpty> settings = std::make_shared<SourceGroupSettingsCppEmpty>(sourceGroupId, m_projectSettings.get());
addMsvcCompatibilityFlagsOnDemand(settings);
executeSoureGroupSetup<SourceGroupSettingsCppEmpty>(settings);
executeSourceGroupSetup<SourceGroupSettingsCppEmpty>(settings);
}
break;
case SOURCE_GROUP_CXX_CDB:
{
std::shared_ptr<SourceGroupSettingsCxxCdb> settings = std::make_shared<SourceGroupSettingsCxxCdb>(sourceGroupId, m_projectSettings.get());
executeSoureGroupSetup<SourceGroupSettingsCxxCdb>(settings);
executeSourceGroupSetup<SourceGroupSettingsCxxCdb>(settings);
}
break;
case SOURCE_GROUP_CXX_CODEBLOCKS:
{
std::shared_ptr<SourceGroupSettingsCxxCodeblocks> settings = std::make_shared<SourceGroupSettingsCxxCodeblocks>(sourceGroupId, m_projectSettings.get());
addMsvcCompatibilityFlagsOnDemand(settings);
executeSoureGroupSetup<SourceGroupSettingsCxxCodeblocks>(settings);
executeSourceGroupSetup<SourceGroupSettingsCxxCodeblocks>(settings);
}
break;
case SOURCE_GROUP_CXX_SONARGRAPH:
{
std::shared_ptr<SourceGroupSettingsCxxSonargraph> settings = std::make_shared<SourceGroupSettingsCxxSonargraph>(sourceGroupId, m_projectSettings.get());
addMsvcCompatibilityFlagsOnDemand(settings);
executeSoureGroupSetup<SourceGroupSettingsCxxSonargraph>(settings);
executeSourceGroupSetup<SourceGroupSettingsCxxSonargraph>(settings);
}
break;
case SOURCE_GROUP_CXX_VS:
{
std::shared_ptr<SourceGroupSettingsCxxCdbVs> settings = std::make_shared<SourceGroupSettingsCxxCdbVs>(sourceGroupId, m_projectSettings.get());
executeSoureGroupSetup<SourceGroupSettingsCxxCdbVs>(settings);
executeSourceGroupSetup<SourceGroupSettingsCxxCdbVs>(settings);
}
break;
case SOURCE_GROUP_JAVA_EMPTY:
{
std::shared_ptr<SourceGroupSettingsJavaEmpty> settings = std::make_shared<SourceGroupSettingsJavaEmpty>(sourceGroupId, m_projectSettings.get());
executeSoureGroupSetup<SourceGroupSettingsJavaEmpty>(settings);
executeSourceGroupSetup<SourceGroupSettingsJavaEmpty>(settings);
}
break;
case SOURCE_GROUP_JAVA_MAVEN:
@@ -1056,7 +1077,7 @@ void QtProjectWizzard::selectedProjectType(SourceGroupType sourceGroupType)
L"/maven"
)
);
executeSoureGroupSetup<SourceGroupSettingsJavaMaven>(settings);
executeSourceGroupSetup<SourceGroupSettingsJavaMaven>(settings);
}
break;
case SOURCE_GROUP_JAVA_GRADLE:
@@ -1070,13 +1091,19 @@ void QtProjectWizzard::selectedProjectType(SourceGroupType sourceGroupType)
L"/gradle"
)
);
executeSoureGroupSetup<SourceGroupSettingsJavaGradle>(settings);
executeSourceGroupSetup<SourceGroupSettingsJavaGradle>(settings);
}
break;
case SOURCE_GROUP_JAVA_SONARGRAPH:
case SOURCE_GROUP_JAVA_SONARGRAPH:
{
std::shared_ptr<SourceGroupSettingsJavaSonargraph> settings = std::make_shared<SourceGroupSettingsJavaSonargraph>(sourceGroupId, m_projectSettings.get());
executeSoureGroupSetup<SourceGroupSettingsJavaSonargraph>(settings);
executeSourceGroupSetup<SourceGroupSettingsJavaSonargraph>(settings);
}
break;
case SOURCE_GROUP_CUSTOM_COMMAND:
{
std::shared_ptr<SourceGroupSettingsCustomCommand> settings = std::make_shared<SourceGroupSettingsCustomCommand>(sourceGroupId, m_projectSettings.get());
executeSourceGroupSetup<SourceGroupSettingsCustomCommand>(settings);
}
break;
case SOURCE_GROUP_UNKNOWN:
@@ -42,7 +42,7 @@ protected:
private:
template <typename SettingsType>
void executeSoureGroupSetup(std::shared_ptr<SettingsType> settings);
void executeSourceGroupSetup(std::shared_ptr<SettingsType> settings);
QtProjectWizzardWindow* createWindowWithContent(
std::function<QtProjectWizzardContent*(QtProjectWizzardWindow*)> func);
@@ -0,0 +1,92 @@
#include "QtProjectWizzardContentCustomCommand.h"
#include <QLineEdit>
#include <QMessageBox>
#include <boost/filesystem/path.hpp>
#include "FileSystem.h"
#include "ProjectSettings.h"
#include "SourceGroupSettingsCustomCommand.h"
#include "SqliteIndexStorage.h"
QtProjectWizzardContentCustomCommand::QtProjectWizzardContentCustomCommand(
std::shared_ptr<SourceGroupSettingsCustomCommand> settings,
QtProjectWizzardWindow* window
)
: QtProjectWizzardContent(window)
, m_settings(settings)
, m_customCommand(nullptr)
{
}
void QtProjectWizzardContentCustomCommand::populate(QGridLayout* layout, int& row)
{
if (!isInForm())
{
layout->setRowMinimumHeight(row, 15);
row++;
}
QLabel* nameLabel = createFormLabel("Custom Command");
addHelpButton(
"Custom Command",
"<p>Specify the commandline call that will be executed for each source file in this Source Group. "
"You can use the following variables, $SOURCE_PATH is mandatory.</p>"
"<ul>"
"<li><b>$SOURCE_PATH</b> - Path to each source file (mandatory)</li>"
"<li><b>$PROJECT_PATH</b> - Path to project file: \"" +
QString::fromStdWString(m_settings->getProjectSettings()->getProjectFilePath().wstr()) + "\"</li>"
"<li><b>$DB_PATH</b> - Path to database file: \"" +
QString::fromStdWString(m_settings->getProjectSettings()->getTempDBFilePath().wstr()) + "\"</li>"
"<li><b>$STORAGE_VERSION</b> - Storage version used by this Sourcetrail version: \"" +
QString::number(SqliteIndexStorage::getStorageVersion()) + "\"</li>"
"</ul>",
layout, row
);
m_customCommand = new QLineEdit();
m_customCommand->setObjectName("name");
m_customCommand->setAttribute(Qt::WA_MacShowFocusRect, 0);
layout->addWidget(nameLabel, row, QtProjectWizzardWindow::FRONT_COL, Qt::AlignRight);
layout->addWidget(m_customCommand, row, QtProjectWizzardWindow::BACK_COL);
layout->setRowMinimumHeight(row, 30);
row++;
if (!isInForm())
{
layout->setRowMinimumHeight(row, 15);
layout->setRowStretch(row, 1);
}
}
void QtProjectWizzardContentCustomCommand::load()
{
m_customCommand->setText(QString::fromStdWString(m_settings->getCustomCommand()));
}
void QtProjectWizzardContentCustomCommand::save()
{
m_settings->setCustomCommand(m_customCommand->text().toStdWString());
}
bool QtProjectWizzardContentCustomCommand::check()
{
if (m_customCommand->text().isEmpty())
{
QMessageBox msgBox;
msgBox.setText("Please enter a custom command.");
msgBox.exec();
return false;
}
if (m_customCommand->text().toStdWString().find(L"$SOURCE_PATH") == std::wstring::npos)
{
QMessageBox msgBox;
msgBox.setText("The variable $SOURCE_PATH is missing in the custom command.");
msgBox.exec();
return false;
}
return true;
}
@@ -0,0 +1,32 @@
#ifndef QT_PROJECT_WIZZARD_CONTENT_CUSTOM_COMMAND_H
#define QT_PROJECT_WIZZARD_CONTENT_CUSTOM_COMMAND_H
#include "QtProjectWizzardContent.h"
class QLineEdit;
class SourceGroupSettingsCustomCommand;
class QtProjectWizzardContentCustomCommand
: public QtProjectWizzardContent
{
Q_OBJECT
public:
QtProjectWizzardContentCustomCommand(
std::shared_ptr<SourceGroupSettingsCustomCommand> settings,
QtProjectWizzardWindow* window);
// QtProjectWizzardContent implementation
virtual void populate(QGridLayout* layout, int& row) override;
virtual void load() override;
virtual void save() override;
virtual bool check() override;
private:
std::shared_ptr<SourceGroupSettingsCustomCommand> m_settings;
QLineEdit* m_customCommand;
};
#endif // QT_PROJECT_WIZZARD_CONTENT_CUSTOM_COMMAND_H
@@ -8,12 +8,14 @@
#include "DialogView.h"
#include "IndexerCommandCxx.h"
#include "SourceGroupCxxEmpty.h"
#include "SourceGroupJavaEmpty.h"
#include "QtDialogView.h"
#include "QtPathListDialog.h"
#include "QtSelectPathsDialog.h"
#include "SourceGroupCustomCommand.h"
#include "SourceGroupCxxEmpty.h"
#include "SourceGroupJavaEmpty.h"
#include "ApplicationSettings.h"
#include "SourceGroupSettingsCustomCommand.h"
#include "SourceGroupSettingsCxx.h"
#include "SourceGroupSettingsCxxCdb.h"
#include "SourceGroupSettingsCxxCodeblocks.h"
@@ -252,6 +254,10 @@ std::vector<FilePath> QtProjectWizzardContentPathsSource::getFilePaths() const
{
allSourceFilePaths = SourceGroupJavaEmpty(settings).getAllSourceFilePaths();
}
else if (std::shared_ptr<SourceGroupSettingsCustomCommand> settings = std::dynamic_pointer_cast<SourceGroupSettingsCustomCommand>(m_settings))
{
allSourceFilePaths = SourceGroupCustomCommand(settings).getAllSourceFilePaths();
}
return utility::getAsRelativeIfShorter(
utility::toVector(allSourceFilePaths),
@@ -42,6 +42,7 @@ void QtProjectWizzardContentSelect::populate(QGridLayout* layout, int& row)
sourceGroupInfos[LANGUAGE_JAVA].push_back(SourceGroupInfo(SOURCE_GROUP_JAVA_MAVEN));
sourceGroupInfos[LANGUAGE_JAVA].push_back(SourceGroupInfo(SOURCE_GROUP_JAVA_GRADLE));
sourceGroupInfos[LANGUAGE_JAVA].push_back(SourceGroupInfo(SOURCE_GROUP_JAVA_SONARGRAPH));
sourceGroupInfos[LANGUAGE_CUSTOM].push_back(SourceGroupInfo(SOURCE_GROUP_CUSTOM_COMMAND));
// define which icons should be used for which kind of source group
m_sourceGroupTypeIconName[SOURCE_GROUP_C_EMPTY] = L"empty_icon";
@@ -54,6 +55,7 @@ void QtProjectWizzardContentSelect::populate(QGridLayout* layout, int& row)
m_sourceGroupTypeIconName[SOURCE_GROUP_JAVA_MAVEN] = L"mvn_icon";
m_sourceGroupTypeIconName[SOURCE_GROUP_JAVA_GRADLE] = L"gradle_icon";
m_sourceGroupTypeIconName[SOURCE_GROUP_JAVA_SONARGRAPH] = L"sonargraph_icon";
m_sourceGroupTypeIconName[SOURCE_GROUP_CUSTOM_COMMAND] = L"empty_icon";
// define descriptions for each kind of Source Group
m_sourceGroupTypeDescriptions[SOURCE_GROUP_C_EMPTY] = "Create a new Sourcetrail Source Group by defining which C files will be indexed.";
@@ -78,9 +80,12 @@ void QtProjectWizzardContentSelect::populate(QGridLayout* layout, int& row)
m_sourceGroupTypeDescriptions[SOURCE_GROUP_JAVA_GRADLE] = "Create a new Source Group from an existing Gradle project.";
m_sourceGroupTypeDescriptions[SOURCE_GROUP_JAVA_SONARGRAPH] =
"Create a new Source Group from an existing <a href=\"https://www.hello2morrow.com/products/sonargraph\">Sonargraph</a> project file.";
m_sourceGroupTypeDescriptions[SOURCE_GROUP_CUSTOM_COMMAND] = "Create a new Source Group executing a custom command on each source file. "
"This Source Group type can be used on <a href=\"https://github.com/CoatiSoftware/SourcetrailDB\">SourcetrailDB</a> binaries that add "
"custom language support";
QVBoxLayout* vlayout = new QVBoxLayout();
vlayout->setContentsMargins(0, 30, 0, 0);
vlayout->setContentsMargins(0, 10, 0, 0);
vlayout->setSpacing(10);
m_languages = new QButtonGroup();
+9 -1
View File
@@ -96,7 +96,8 @@ int utility::executeProcessAndGetExitCode(
const std::wstring& commandPath,
const std::vector<std::wstring>& commandArguments,
const FilePath& workingDirectory,
const int timeout
const int timeout,
std::wstring* processOutput
){
QProcess process;
@@ -124,7 +125,14 @@ int utility::executeProcessAndGetExitCode(
}
int exitCode = process.exitCode();
if (processOutput != nullptr)
{
*processOutput = utility::trim(QString(process.readAll()).toStdWString());
}
process.close();
return exitCode;
}
+2 -1
View File
@@ -18,7 +18,8 @@ namespace utility
const std::wstring& commandPath,
const std::vector<std::wstring>& commandArguments,
const FilePath& workingDirectory = FilePath(),
const int timeout = 30000
const int timeout = 30000,
std::wstring* processOutput = nullptr
);
void killRunningProcesses();