Files
Sourcetrail/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp
T
malte_langkabel 9bcde198a5 logic: add auto-detection for JRE System Library
* fixed error columns are not saved to database correctly
* implemented setting JRE System Library paths in app settings
* added detector for JRE System Library that not use Java Runtime specified in AppSettings but detects JRE on its own by reusing the JavaPathDetector.
* added option to use JRE System Library in JavaSourceGroup
2017-07-10 18:12:52 +02:00

515 lines
16 KiB
C++

#include "qt/window/project_wizzard/QtProjectWizzardContentPaths.h"
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QMessageBox>
#include <QVBoxLayout>
#include "qt/element/QtDirectoryListBox.h"
#include "qt/window/QtSelectPathsDialog.h"
#include "settings/ApplicationSettings.h"
#include "settings/SourceGroupSettingsCxx.h"
#include "settings/SourceGroupSettingsJava.h"
#include "utility/CompilationDatabase.h"
#include "utility/file/FileManager.h"
#include "utility/utility.h"
#include "utility/utilityPathDetection.h"
QtProjectWizzardContentPaths::QtProjectWizzardContentPaths(std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window)
: QtProjectWizzardContent(window)
, m_settings(settings)
, m_makePathsRelativeToProjectFileLocation(true)
{
}
void QtProjectWizzardContentPaths::populate(QGridLayout* layout, int& row)
{
QLabel* label = createFormLabel(m_titleString);
layout->addWidget(label, row, QtProjectWizzardWindow::FRONT_COL, Qt::AlignTop);
if (m_helpString.size() > 0)
{
addHelpButton(m_helpString, layout, row);
}
m_list = new QtDirectoryListBox(this, m_titleString);
if (m_makePathsRelativeToProjectFileLocation && m_settings)
{
m_list->setRelativeRootDirectory(m_settings->getProjectFileLocation());
}
layout->addWidget(m_list, row, QtProjectWizzardWindow::BACK_COL);
row++;
if (m_showFilesString.size() > 0)
{
addFilesButton(m_showFilesString, layout, row);
row++;
}
if (m_pathDetector)
{
addDetection(layout, row);
row++;
}
}
bool QtProjectWizzardContentPaths::check()
{
QString missingPaths;
std::vector<FilePath> paths = m_list->getList();
if (m_settings)
{
paths = m_settings->makePathsExpandedAndAbsolute(paths);
}
for (const FilePath& path : paths)
{
if (!path.exists())
{
missingPaths.append(path.str().c_str());
missingPaths.append("\n");
break;
}
}
if (!missingPaths.isEmpty())
{
QMessageBox msgBox;
msgBox.setText("Some provided paths do not exist at \"" + m_titleString + "\".");
msgBox.setDetailedText(missingPaths);
msgBox.exec();
return false;
}
return true;
}
void QtProjectWizzardContentPaths::setTitleString(const QString& title)
{
m_titleString = title;
}
void QtProjectWizzardContentPaths::setHelpString(const QString& help)
{
m_helpString = help;
}
void QtProjectWizzardContentPaths::addDetection(QGridLayout* layout, int row)
{
std::vector<std::string> detectorNames = m_pathDetector->getWorkingDetectorNames();
if (!detectorNames.size())
{
return;
}
QLabel* label = new QLabel("Auto detection from:");
m_detectorBox = new QComboBox();
for (const std::string& detectorName: detectorNames)
{
m_detectorBox->addItem(detectorName.c_str());
}
QPushButton* button = new QPushButton("detect");
button->setObjectName("windowButton");
connect(button, SIGNAL(clicked()), this, SLOT(detectionClicked()));
QHBoxLayout* hlayout = new QHBoxLayout();
hlayout->setContentsMargins(0, 0, 0, 0);
hlayout->addWidget(label);
hlayout->addWidget(m_detectorBox);
hlayout->addWidget(button);
QWidget* detectionWidget = new QWidget();
detectionWidget->setLayout(hlayout);
layout->addWidget(detectionWidget, row, QtProjectWizzardWindow::BACK_COL, Qt::AlignLeft | Qt::AlignTop);
}
void QtProjectWizzardContentPaths::detectionClicked()
{
std::vector<FilePath> paths = m_pathDetector->getPaths(m_detectorBox->currentText().toStdString());
std::vector<FilePath> oldPaths = m_list->getList();
m_list->setList(utility::unique(utility::concat(oldPaths, paths)));
}
QtProjectWizzardContentPathsSource::QtProjectWizzardContentPathsSource(
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window
)
: QtProjectWizzardContentPaths(settings, window)
{
m_showFilesString = "show files";
setTitleString("Indexed Paths");
setHelpString(
"Indexed Paths define the files and directories that will be indexed by Sourcetrail. Provide a directory to recursively "
"add all contained files.<br />"
"<br />"
"If your project's source code resides in one location, but generated source files are kept at a different location, "
"you will also need to add that directory.<br />"
"<br />"
"You can make use of environment variables with ${ENV_VAR}."
);
}
void QtProjectWizzardContentPathsSource::load()
{
m_list->setList(m_settings->getSourcePaths());
}
void QtProjectWizzardContentPathsSource::save()
{
m_settings->setSourcePaths(m_list->getList());
}
std::vector<std::string> QtProjectWizzardContentPathsSource::getFileNames() const
{
FileManager fileManager;
fileManager.update(
m_settings->getSourcePathsExpandedAndAbsolute(),
m_settings->getExcludePathsExpandedAndAbsolute(),
m_settings->getSourceExtensions()
);
const FilePath projectPath = m_settings->getProjectFileLocation();
std::vector<std::string> list;
for (FilePath path: fileManager.getAllSourceFilePaths())
{
if (projectPath.exists())
{
path = path.relativeTo(projectPath);
}
list.push_back(path.str());
}
return list;
}
QString QtProjectWizzardContentPathsSource::getFileNamesTitle() const
{
return "Indexed Files";
}
QString QtProjectWizzardContentPathsSource::getFileNamesDescription() const
{
return " files will be indexed.";
}
QtProjectWizzardContentPathsCDBHeader::QtProjectWizzardContentPathsCDBHeader(
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window
)
: QtProjectWizzardContentPathsSource(settings, window)
{
m_showFilesString = "";
setTitleString("Indexed Header Paths");
setHelpString(
"Define which header files should be indexed by Sourcetrail. Provide a directory to recursively add all contained files. "
"Every time an included header is encountered, Sourcetrail will check if the file is part of the indexed headers to "
"decide whether or not to index it.<br />"
"<br />"
"Just enter the root path of your project if you want Sourcetrail to index all contained headers it encounters.<br />"
"<br />"
"You can make use of environment variables with ${ENV_VAR}."
);
}
void QtProjectWizzardContentPathsCDBHeader::populate(QGridLayout* layout, int& row)
{
QtProjectWizzardContentPaths::populate(layout, row);
QPushButton* button = new QPushButton("Select from Include Paths");
button->setObjectName("windowButton");
connect(button, SIGNAL(clicked()), this, SLOT(buttonClicked()));
layout->addWidget(button, row, QtProjectWizzardWindow::BACK_COL, Qt::AlignRight | Qt::AlignTop);
row++;
}
bool QtProjectWizzardContentPathsCDBHeader::check()
{
if (!m_list->getList().size())
{
QMessageBox msgBox;
msgBox.setText("You didn't specify any Indexed Header Paths.");
msgBox.setInformativeText(
"Sourcetrail will only index the source files listed in the compilation database file and none of the included "
"header files.");
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Ok);
int ret = msgBox.exec();
return ret == QMessageBox::Ok;
}
else
{
return QtProjectWizzardContentPaths::check();
}
}
void QtProjectWizzardContentPathsCDBHeader::buttonClicked()
{
save();
if (!m_filesDialog)
{
FilePath cdbPath = dynamic_cast<SourceGroupSettingsCxx*>(m_settings.get())->getCompilationDatabasePathExpandedAndAbsolute();
if (!cdbPath.exists())
{
QMessageBox msgBox;
msgBox.setText("The provided Compilation Database path does not exist.");
msgBox.setDetailedText(QString::fromStdString(cdbPath.str()));
msgBox.exec();
return;
}
m_filesDialog = std::make_shared<QtSelectPathsDialog>(
"Select from Include Paths",
"The list contains all Include Paths found in the Compilation Database. Red paths do not exist. Select the "
"paths containing the header files you want to index with Sourcetrail.");
m_filesDialog->setup();
connect(m_filesDialog.get(), SIGNAL(finished()), this, SLOT(savedFilesDialog()));
connect(m_filesDialog.get(), SIGNAL(canceled()), this, SLOT(closedFilesDialog()));
utility::CompilationDatabase cdb(cdbPath.str());
std::vector<FilePath> sourcePaths = m_settings->getSourcePaths();
std::vector<FilePath> cdbHeaderPaths = utility::unique(utility::concat(sourcePaths, cdb.getAllHeaderPaths()));
dynamic_cast<QtSelectPathsDialog*>(m_filesDialog.get())->setPathsList(cdbHeaderPaths, sourcePaths);
}
m_filesDialog->showWindow();
m_filesDialog->raise();
}
void QtProjectWizzardContentPathsCDBHeader::savedFilesDialog()
{
// TODO: extend instead of replace
m_list->setList(dynamic_cast<QtSelectPathsDialog*>(m_filesDialog.get())->getPathsList());
closedFilesDialog();
}
QtProjectWizzardContentPathsExclude::QtProjectWizzardContentPathsExclude(
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window
)
: QtProjectWizzardContentPaths(settings, window)
{
setTitleString("Exclude Paths");
setHelpString(
"Exclude Paths define the files and directories that will be left out from indexing.<br />"
"<br />"
"You can make use of environment variables with ${ENV_VAR}.");
}
void QtProjectWizzardContentPathsExclude::load()
{
m_list->setList(m_settings->getExcludePaths());
}
void QtProjectWizzardContentPathsExclude::save()
{
m_settings->setExcludePaths(m_list->getList());
}
QtProjectWizzardContentPathsHeaderSearch::QtProjectWizzardContentPathsHeaderSearch(
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window, bool isCDB
)
: QtProjectWizzardContentPaths(settings, window)
{
setTitleString(isCDB ? "Additional Include Paths" : "Include Paths");
setHelpString(
((isCDB ? "<b>Note</b>: Use the Additional Include Paths to add paths that are missing in the CDB.<br /><br />" : "") + std::string(
"Include Paths are used for resolving #include directives in the indexed source and header files. These paths are "
"usually passed to the compiler with the '-I' or '-iquote' flags.<br />"
"<br />"
"Add all paths #include directives throughout your project are relative to. If all #include directives are "
"specified relative to the project's root directory, please add that root directory here.<br />"
"<br />"
"If your project also includes files from external libraries (e.g. boost), please add these directories as well "
"(e.g. add '&lt;boost_home&gt;/include').<br />"
"<br />"
"You can make use of environment variables with ${ENV_VAR}.")).c_str()
);
}
void QtProjectWizzardContentPathsHeaderSearch::load()
{
std::shared_ptr<SourceGroupSettingsCxx> cxxSettings = std::dynamic_pointer_cast<SourceGroupSettingsCxx>(m_settings);
if (cxxSettings)
{
m_list->setList(cxxSettings->getHeaderSearchPaths());
}
}
void QtProjectWizzardContentPathsHeaderSearch::save()
{
std::shared_ptr<SourceGroupSettingsCxx> cxxSettings = std::dynamic_pointer_cast<SourceGroupSettingsCxx>(m_settings);
if (cxxSettings)
{
cxxSettings->setHeaderSearchPaths(m_list->getList());
}
}
bool QtProjectWizzardContentPathsHeaderSearch::isScrollAble() const
{
return true;
}
QtProjectWizzardContentPathsHeaderSearchGlobal::QtProjectWizzardContentPathsHeaderSearchGlobal(
QtProjectWizzardWindow* window
)
: QtProjectWizzardContentPaths(std::shared_ptr<SourceGroupSettings>(), window)
{
setTitleString("Global Include Paths");
setHelpString(
"The Global Include Paths will be used in all your projects - in addition to the project specific Include Paths. "
"These paths are usually passed to the compiler with the '-isystem' flag.<br />"
"<br />"
"Use them to add system header paths (See <a href=\"https://sourcetrail.com/documentation/#FindingSystemHeaderLocations\">"
"Finding System Header Locations</a> or use the auto detection below)."
);
m_pathDetector = utility::getCxxHeaderPathDetector();
m_makePathsRelativeToProjectFileLocation = false;
}
void QtProjectWizzardContentPathsHeaderSearchGlobal::load()
{
m_list->setList(ApplicationSettings::getInstance()->getHeaderSearchPaths());
}
void QtProjectWizzardContentPathsHeaderSearchGlobal::save()
{
ApplicationSettings::getInstance()->setHeaderSearchPaths(m_list->getList());
ApplicationSettings::getInstance()->save();
}
QtProjectWizzardContentPathsFrameworkSearch::QtProjectWizzardContentPathsFrameworkSearch(
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window, bool isCDB
)
: QtProjectWizzardContentPaths(settings, window)
{
setTitleString(isCDB ? "Additional Framework Search Paths" : "Framework Search Paths");
setHelpString(
"Framework Search Paths define where MacOS framework containers (.framework), that your project depends on, are "
"found. These paths are usually passed to the compiler with the '-iframework' flag.<br />"
"<br />"
"You can make use of environment variables with ${ENV_VAR}."
);
}
void QtProjectWizzardContentPathsFrameworkSearch::load()
{
std::shared_ptr<SourceGroupSettingsCxx> cxxSettings = std::dynamic_pointer_cast<SourceGroupSettingsCxx>(m_settings);
if (cxxSettings)
{
m_list->setList(cxxSettings->getFrameworkSearchPaths());
}
}
void QtProjectWizzardContentPathsFrameworkSearch::save()
{
std::shared_ptr<SourceGroupSettingsCxx> cxxSettings = std::dynamic_pointer_cast<SourceGroupSettingsCxx>(m_settings);
if (cxxSettings)
{
cxxSettings->setFrameworkSearchPaths(m_list->getList());
}
}
bool QtProjectWizzardContentPathsFrameworkSearch::isScrollAble() const
{
return true;
}
QtProjectWizzardContentPathsFrameworkSearchGlobal::QtProjectWizzardContentPathsFrameworkSearchGlobal(
QtProjectWizzardWindow* window
)
: QtProjectWizzardContentPaths(std::shared_ptr<SourceGroupSettings>(), window)
{
setTitleString("Global Framework Search Paths");
setHelpString(
"The Global Framework Search Paths will be used in all your projects - in addition to the project specific "
"Framework Search Paths.<br />"
"<br />"
"They define where MacOS framework containers (.framework) are found "
"(See <a href=\"https://sourcetrail.com/documentation/#FindingSystemHeaderLocations\">"
"Finding System Header Locations</a> or use the auto detection below)."
);
m_pathDetector = utility::getCxxFrameworkPathDetector();
m_makePathsRelativeToProjectFileLocation = false;
}
void QtProjectWizzardContentPathsFrameworkSearchGlobal::load()
{
m_list->setList(ApplicationSettings::getInstance()->getFrameworkSearchPaths());
}
void QtProjectWizzardContentPathsFrameworkSearchGlobal::save()
{
ApplicationSettings::getInstance()->setFrameworkSearchPaths(m_list->getList());
ApplicationSettings::getInstance()->save();
}
QtProjectWizzardContentPathsClassJava::QtProjectWizzardContentPathsClassJava(
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window
)
: QtProjectWizzardContentPaths(settings, window)
{
setTitleString("Class Path");
setHelpString(
"Enter all the .jar files your project depends on. If your project depends on uncompiled java code that should "
"not be indexed, please add the root directory of those .java files here (the one where all the package names are relative to).<br />"
"<br />"
"You can make use of environment variables with ${ENV_VAR}."
);
}
void QtProjectWizzardContentPathsClassJava::populate(QGridLayout* layout, int& row)
{
QtProjectWizzardContentPaths::populate(layout, row);
QLabel* label = createFormLabel("JRE System Library");
layout->addWidget(label, row, QtProjectWizzardWindow::FRONT_COL, Qt::AlignTop);
m_useJreSystemLibraryCheckBox = new QCheckBox("Use JRE System Library", this);
layout->addWidget(m_useJreSystemLibraryCheckBox, row, QtProjectWizzardWindow::BACK_COL);
row++;
}
void QtProjectWizzardContentPathsClassJava::load()
{
std::shared_ptr<SourceGroupSettingsJava> javaSettings = std::dynamic_pointer_cast<SourceGroupSettingsJava>(m_settings);
if (javaSettings)
{
m_list->setList(javaSettings->getClasspath());
m_useJreSystemLibraryCheckBox->setChecked(javaSettings->getUseJreSystemLibrary());
}
}
void QtProjectWizzardContentPathsClassJava::save()
{
std::shared_ptr<SourceGroupSettingsJava> javaSettings = std::dynamic_pointer_cast<SourceGroupSettingsJava>(m_settings);
if (javaSettings)
{
javaSettings->setClasspath(m_list->getList());
javaSettings->setUseJreSystemLibrary(m_useJreSystemLibraryCheckBox->isChecked());
}
}