forked from qt-creator/qt-creator
ClangTools: Make file selection dialog searchable/filterable
Allow filtering for open and edited documents. Add also search functionality (triggerable by e.g. Ctrl+F). Change-Id: Ib41400abfd3b81371afddd56b88ff1b9bf8b9bcd Reviewed-by: Cristian Adam <cristian.adam@qt.io> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -48,12 +48,33 @@ public:
|
||||
CppTools::ProjectFile::Kind kind;
|
||||
CppTools::ProjectPart::Ptr projectPart;
|
||||
};
|
||||
using FileInfos = std::vector<FileInfo>;
|
||||
|
||||
inline bool operator==(const FileInfo &lhs, const FileInfo &rhs) {
|
||||
return lhs.file == rhs.file;
|
||||
}
|
||||
|
||||
using FileInfos = std::vector<FileInfo>;
|
||||
class FileInfoSelection {
|
||||
public:
|
||||
QSet<Utils::FilePath> dirs;
|
||||
QSet<Utils::FilePath> files;
|
||||
};
|
||||
|
||||
class FileInfoProvider {
|
||||
public:
|
||||
QString displayName;
|
||||
FileInfos fileInfos;
|
||||
FileInfoSelection selection;
|
||||
|
||||
enum ExpandPolicy {
|
||||
All,
|
||||
Limited,
|
||||
} expandPolicy = All;
|
||||
|
||||
using OnSelectionAccepted = std::function<void(const FileInfoSelection &selection)>;
|
||||
OnSelectionAccepted onSelectionAccepted;
|
||||
};
|
||||
using FileInfoProviders = std::vector<FileInfoProvider>;
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangTools
|
||||
|
@@ -27,22 +27,19 @@
|
||||
|
||||
#include "ui_clangselectablefilesdialog.h"
|
||||
|
||||
#include "clangtoolsprojectsettings.h"
|
||||
#include "clangtoolssettings.h"
|
||||
#include "clangtoolsutils.h"
|
||||
|
||||
#include <cpptools/compileroptionsbuilder.h>
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/cpptoolsreuse.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/find/itemviewfind.h>
|
||||
#include <cpptools/projectinfo.h>
|
||||
#include <cpptools/projectpart.h>
|
||||
|
||||
#include <projectexplorer/selectablefilesmodel.h>
|
||||
#include <texteditor/textdocument.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardItem>
|
||||
|
||||
using namespace CppTools;
|
||||
using namespace Utils;
|
||||
@@ -95,48 +92,84 @@ class SelectableFilesModel : public ProjectExplorer::SelectableFilesModel
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SelectableFilesModel(const CppTools::ProjectInfo &projectInfo, const FileInfos &allFileInfos)
|
||||
SelectableFilesModel()
|
||||
: ProjectExplorer::SelectableFilesModel(nullptr)
|
||||
{}
|
||||
|
||||
void buildTree(ProjectExplorer::Project *project, const FileInfos &fileInfos)
|
||||
{
|
||||
buildTree(projectInfo.project(), allFileInfos);
|
||||
beginResetModel();
|
||||
m_root->fullPath = project->projectFilePath();
|
||||
m_root->name = project->projectFilePath().fileName();
|
||||
m_root->isDir = true;
|
||||
|
||||
FileInfos outOfBaseDirFiles;
|
||||
Tree *projectDirTree = buildProjectDirTree(project->projectDirectory(),
|
||||
fileInfos,
|
||||
outOfBaseDirFiles);
|
||||
if (outOfBaseDirFiles.empty()) {
|
||||
// Showing the project file and beneath the project dir is pointless in this case,
|
||||
// so get rid of the root node and modify the project dir node as the new root node.
|
||||
projectDirTree->name = m_root->name;
|
||||
projectDirTree->fullPath = m_root->fullPath;
|
||||
projectDirTree->parent = m_root->parent;
|
||||
|
||||
delete m_root; // OK, it has no files / child dirs.
|
||||
|
||||
m_root = projectDirTree;
|
||||
} else {
|
||||
// Set up project dir node as sub node of the project file node
|
||||
linkDirNode(m_root, projectDirTree);
|
||||
|
||||
// Add files outside of the base directory to a separate node
|
||||
Tree *externalFilesNode = createDirNode(SelectableFilesDialog::tr(
|
||||
"Files outside of the base directory"),
|
||||
FilePath::fromString("/"));
|
||||
linkDirNode(m_root, externalFilesNode);
|
||||
for (const FileInfo &fileInfo : outOfBaseDirFiles)
|
||||
linkFileNode(externalFilesNode, createFileNode(fileInfo, true));
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
// Returns the minimal selection that can restore all selected files.
|
||||
//
|
||||
// For example, if a directory node if fully checked, there is no need to
|
||||
// save all the children of that node.
|
||||
void minimalSelection(QSet<FilePath> &checkedDirs, QSet<FilePath> &checkedFiles) const
|
||||
void minimalSelection(FileInfoSelection &selection) const
|
||||
{
|
||||
selection.dirs.clear();
|
||||
selection.files.clear();
|
||||
traverse(index(0, 0, QModelIndex()), [&](const QModelIndex &index){
|
||||
auto node = static_cast<Tree *>(index.internalPointer());
|
||||
|
||||
if (node->checked == Qt::Checked) {
|
||||
if (node->isDir) {
|
||||
checkedDirs += node->fullPath;
|
||||
selection.dirs += node->fullPath;
|
||||
return false; // Do not descend further.
|
||||
}
|
||||
|
||||
checkedFiles += node->fullPath;
|
||||
selection.files += node->fullPath;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void restoreMinimalSelection(const QSet<FilePath> &dirs, const QSet<FilePath> &files)
|
||||
void restoreMinimalSelection(const FileInfoSelection &selection)
|
||||
{
|
||||
if (dirs.isEmpty() && files.isEmpty())
|
||||
if (selection.dirs.isEmpty() && selection.files.isEmpty())
|
||||
return;
|
||||
|
||||
traverse(index(0, 0, QModelIndex()), [&](const QModelIndex &index){
|
||||
auto node = static_cast<Tree *>(index.internalPointer());
|
||||
|
||||
if (node->isDir && dirs.contains(node->fullPath)) {
|
||||
if (node->isDir && selection.dirs.contains(node->fullPath)) {
|
||||
setData(index, Qt::Checked, Qt::CheckStateRole);
|
||||
return false; // Do not descend further.
|
||||
}
|
||||
|
||||
if (!node->isDir && files.contains(node->fullPath))
|
||||
if (!node->isDir && selection.files.contains(node->fullPath))
|
||||
setData(index, Qt::Checked, Qt::CheckStateRole);
|
||||
|
||||
return true;
|
||||
@@ -183,40 +216,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void buildTree(ProjectExplorer::Project *project, const FileInfos &fileInfos)
|
||||
{
|
||||
m_root->fullPath = project->projectFilePath();
|
||||
m_root->name = project->projectFilePath().fileName();
|
||||
m_root->isDir = true;
|
||||
|
||||
FileInfos outOfBaseDirFiles;
|
||||
Tree *projectDirTree = buildProjectDirTree(project->projectDirectory(),
|
||||
fileInfos,
|
||||
outOfBaseDirFiles);
|
||||
if (outOfBaseDirFiles.empty()) {
|
||||
// Showing the project file and beneath the project dir is pointless in this case,
|
||||
// so get rid of the root node and modify the project dir node as the new root node.
|
||||
projectDirTree->name = m_root->name;
|
||||
projectDirTree->fullPath = m_root->fullPath;
|
||||
projectDirTree->parent = m_root->parent;
|
||||
|
||||
delete m_root; // OK, it has no files / child dirs.
|
||||
|
||||
m_root = projectDirTree;
|
||||
} else {
|
||||
// Set up project dir node as sub node of the project file node
|
||||
linkDirNode(m_root, projectDirTree);
|
||||
|
||||
// Add files outside of the base directory to a separate node
|
||||
Tree *externalFilesNode = createDirNode(SelectableFilesDialog::tr(
|
||||
"Files outside of the base directory"),
|
||||
FilePath::fromString("/"));
|
||||
linkDirNode(m_root, externalFilesNode);
|
||||
for (const FileInfo &fileInfo : outOfBaseDirFiles)
|
||||
linkFileNode(externalFilesNode, createFileNode(fileInfo, true));
|
||||
}
|
||||
}
|
||||
|
||||
Tree *buildProjectDirTree(const FilePath &projectDir,
|
||||
const FileInfos &fileInfos,
|
||||
FileInfos &outOfBaseDirFiles) const
|
||||
@@ -265,52 +264,128 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
class FileFilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FileFilterModel(QObject *parent = nullptr)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{}
|
||||
|
||||
private:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
|
||||
{
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
const int rowCount = sourceModel()->rowCount(index);
|
||||
if (rowCount == 0) // No children -> file node!
|
||||
return sourceModel()->data(index).toString().contains(filterRegExp());
|
||||
for (int row = 0; row < rowCount; ++row) {
|
||||
if (filterAcceptsRow(row, index))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
|
||||
const FileInfos &allFileInfos)
|
||||
const FileInfoProviders &fileInfoProviders,
|
||||
int initialProviderIndex)
|
||||
: QDialog(nullptr)
|
||||
, m_ui(new Ui::SelectableFilesDialog)
|
||||
, m_filesModel(new SelectableFilesModel(projectInfo, allFileInfos))
|
||||
, m_filesModel(new SelectableFilesModel)
|
||||
, m_fileInfoProviders(fileInfoProviders)
|
||||
, m_project(projectInfo.project())
|
||||
, m_analyzeButton(new QPushButton(tr("Analyze"), this))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->filesView->setModel(m_filesModel.get());
|
||||
m_ui->filesView->expandToDepth(2);
|
||||
// Files View
|
||||
// Make find actions available in this dialog, e.g. Strg+F for the view.
|
||||
addAction(Core::ActionManager::command(Core::Constants::FIND_IN_DOCUMENT)->action());
|
||||
addAction(Core::ActionManager::command(Core::Constants::FIND_NEXT)->action());
|
||||
addAction(Core::ActionManager::command(Core::Constants::FIND_PREVIOUS)->action());
|
||||
m_fileView = new QTreeView;
|
||||
m_fileView->setHeaderHidden(true);
|
||||
m_fileView->setModel(m_filesModel.get());
|
||||
m_ui->verticalLayout->addWidget(
|
||||
Core::ItemViewFind::createSearchableWrapper(m_fileView, Core::ItemViewFind::LightColored));
|
||||
|
||||
m_ui->buttons->setStandardButtons(QDialogButtonBox::Cancel);
|
||||
m_ui->buttons->addButton(m_analyzeButton, QDialogButtonBox::AcceptRole);
|
||||
// Filter combo box
|
||||
for (const FileInfoProvider &provider : m_fileInfoProviders) {
|
||||
m_ui->fileFilterComboBox->addItem(provider.displayName);
|
||||
|
||||
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
|
||||
|
||||
// Restore selection
|
||||
if (settings->selectedDirs().isEmpty() && settings->selectedFiles().isEmpty())
|
||||
m_filesModel->selectAllFiles(); // Initially, all files are selected
|
||||
else // Restore selection
|
||||
m_filesModel->restoreMinimalSelection(settings->selectedDirs(), settings->selectedFiles());
|
||||
// Disable item if it has no file infos
|
||||
auto *model = qobject_cast<QStandardItemModel *>(m_ui->fileFilterComboBox->model());
|
||||
QStandardItem *item = model->item(m_ui->fileFilterComboBox->count() - 1);
|
||||
item->setFlags(provider.fileInfos.empty() ? item->flags() & ~Qt::ItemIsEnabled
|
||||
: item->flags() | Qt::ItemIsEnabled);
|
||||
}
|
||||
int providerIndex = initialProviderIndex;
|
||||
if (m_fileInfoProviders[providerIndex].fileInfos.empty())
|
||||
providerIndex = 0;
|
||||
m_ui->fileFilterComboBox->setCurrentIndex(providerIndex);
|
||||
onFileFilterChanged(providerIndex);
|
||||
connect(m_ui->fileFilterComboBox,
|
||||
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&SelectableFilesDialog::onFileFilterChanged);
|
||||
|
||||
// Buttons
|
||||
m_buttons = new QDialogButtonBox;
|
||||
m_buttons->setStandardButtons(QDialogButtonBox::Cancel);
|
||||
m_buttons->addButton(m_analyzeButton, QDialogButtonBox::AcceptRole);\
|
||||
connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
m_analyzeButton->setEnabled(m_filesModel->hasCheckedFiles());
|
||||
connect(m_filesModel.get(), &QAbstractItemModel::dataChanged, [this]() {
|
||||
m_analyzeButton->setEnabled(m_filesModel->hasCheckedFiles());
|
||||
});
|
||||
m_ui->verticalLayout->addWidget(m_buttons);
|
||||
}
|
||||
|
||||
SelectableFilesDialog::~SelectableFilesDialog() = default;
|
||||
|
||||
FileInfos SelectableFilesDialog::filteredFileInfos() const
|
||||
FileInfos SelectableFilesDialog::fileInfos() const
|
||||
{
|
||||
return m_filesModel->selectedFileInfos();
|
||||
}
|
||||
|
||||
int SelectableFilesDialog::currentProviderIndex() const
|
||||
{
|
||||
return m_ui->fileFilterComboBox->currentIndex();
|
||||
}
|
||||
|
||||
void SelectableFilesDialog::onFileFilterChanged(int index)
|
||||
{
|
||||
// Remember previous filter/selection
|
||||
if (m_previousProviderIndex != -1)
|
||||
m_filesModel->minimalSelection(m_fileInfoProviders[m_previousProviderIndex].selection);
|
||||
m_previousProviderIndex = index;
|
||||
|
||||
// Reset model
|
||||
const FileInfoProvider &provider = m_fileInfoProviders[index];
|
||||
m_filesModel->buildTree(m_project, provider.fileInfos);
|
||||
|
||||
// Expand
|
||||
if (provider.expandPolicy == FileInfoProvider::All)
|
||||
m_fileView->expandAll();
|
||||
else
|
||||
m_fileView->expandToDepth(2);
|
||||
|
||||
// Handle selection
|
||||
if (provider.selection.dirs.isEmpty() && provider.selection.files.isEmpty())
|
||||
m_filesModel->selectAllFiles(); // Initially, all files are selected
|
||||
else
|
||||
m_filesModel->restoreMinimalSelection(provider.selection);
|
||||
}
|
||||
|
||||
void SelectableFilesDialog::accept()
|
||||
{
|
||||
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
|
||||
|
||||
QSet<FilePath> checkedDirs;
|
||||
QSet<FilePath> checkedFiles;
|
||||
m_filesModel->minimalSelection(checkedDirs, checkedFiles);
|
||||
settings->setSelectedDirs(checkedDirs);
|
||||
settings->setSelectedFiles(checkedFiles);
|
||||
FileInfoSelection selection;
|
||||
m_filesModel->minimalSelection(selection);
|
||||
FileInfoProvider &provider = m_fileInfoProviders[m_ui->fileFilterComboBox->currentIndex()];
|
||||
provider.onSelectionAccepted(selection);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
@@ -27,13 +27,10 @@
|
||||
|
||||
#include "clangfileinfo.h"
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include <memory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDialogButtonBox;
|
||||
class QPushButton;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -51,18 +48,25 @@ class SelectableFilesDialog : public QDialog
|
||||
|
||||
public:
|
||||
explicit SelectableFilesDialog(const CppTools::ProjectInfo &projectInfo,
|
||||
const FileInfos &allFileInfos);
|
||||
const FileInfoProviders &fileInfoProviders,
|
||||
int initialProviderIndex);
|
||||
~SelectableFilesDialog() override;
|
||||
|
||||
FileInfos filteredFileInfos() const;
|
||||
FileInfos fileInfos() const;
|
||||
int currentProviderIndex() const;
|
||||
|
||||
private:
|
||||
void onFileFilterChanged(int index);
|
||||
void accept() override;
|
||||
|
||||
std::unique_ptr<Ui::SelectableFilesDialog> m_ui;
|
||||
QTreeView *m_fileView = nullptr;
|
||||
QDialogButtonBox *m_buttons = nullptr;
|
||||
std::unique_ptr<SelectableFilesModel> m_filesModel;
|
||||
|
||||
Core::Id m_customDiagnosticConfig;
|
||||
FileInfoProviders m_fileInfoProviders;
|
||||
int m_previousProviderIndex = -1;
|
||||
|
||||
ProjectExplorer::Project *m_project;
|
||||
QPushButton *m_analyzeButton = nullptr;
|
||||
};
|
||||
|
@@ -15,57 +15,17 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeView" name="filesView">
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttons">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
<widget class="QComboBox" name="fileFilterComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttons</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ClangTools::Internal::SelectableFilesDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttons</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ClangTools::Internal::SelectableFilesDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@@ -55,6 +55,8 @@
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <texteditor/textdocument.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fancylineedit.h>
|
||||
#include <utils/fancymainwindow.h>
|
||||
@@ -505,7 +507,11 @@ void ClangTool::startTool(ClangTool::FileSelection fileSelection,
|
||||
ProjectExplorerPlugin::startRunControl(runControl);
|
||||
}
|
||||
|
||||
Diagnostics ClangTool::read(OutputFileFormat outputFileFormat, const QString &logFilePath, const QString &mainFilePath, const QSet<FilePath> &projectFiles, QString *errorMessage) const
|
||||
Diagnostics ClangTool::read(OutputFileFormat outputFileFormat,
|
||||
const QString &logFilePath,
|
||||
const QString &mainFilePath,
|
||||
const QSet<FilePath> &projectFiles,
|
||||
QString *errorMessage) const
|
||||
{
|
||||
const auto acceptFromFilePath = [projectFiles](const Utils::FilePath &filePath) {
|
||||
return projectFiles.contains(filePath);
|
||||
@@ -522,7 +528,7 @@ Diagnostics ClangTool::read(OutputFileFormat outputFileFormat, const QString &lo
|
||||
errorMessage);
|
||||
}
|
||||
|
||||
FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelection) const
|
||||
FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelection)
|
||||
{
|
||||
auto projectInfo = CppTools::CppModelManager::instance()->projectInfo(project);
|
||||
QTC_ASSERT(projectInfo.isValid(), return FileInfos());
|
||||
@@ -533,10 +539,14 @@ FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelect
|
||||
return allFileInfos;
|
||||
|
||||
if (fileSelection == FileSelection::AskUser) {
|
||||
SelectableFilesDialog dialog(projectInfo, allFileInfos);
|
||||
static int initialProviderIndex = 0;
|
||||
SelectableFilesDialog dialog(projectInfo,
|
||||
fileInfoProviders(project, allFileInfos),
|
||||
initialProviderIndex);
|
||||
if (dialog.exec() == QDialog::Rejected)
|
||||
return FileInfos();
|
||||
return dialog.filteredFileInfos();
|
||||
initialProviderIndex = dialog.currentProviderIndex();
|
||||
return dialog.fileInfos();
|
||||
}
|
||||
|
||||
if (fileSelection == FileSelection::CurrentFile) {
|
||||
@@ -605,6 +615,68 @@ void ClangTool::loadDiagnosticsFromFiles()
|
||||
onNewDiagnosticsAvailable(diagnostics);
|
||||
}
|
||||
|
||||
using DocumentPredicate = std::function<bool(Core::IDocument *)>;
|
||||
|
||||
static FileInfos fileInfosMatchingDocuments(const FileInfos &fileInfos,
|
||||
const DocumentPredicate &predicate)
|
||||
{
|
||||
QSet<Utils::FilePath> documentPaths;
|
||||
for (const Core::DocumentModel::Entry *e : Core::DocumentModel::entries()) {
|
||||
if (predicate(e->document))
|
||||
documentPaths.insert(e->fileName());
|
||||
}
|
||||
|
||||
return Utils::filtered(fileInfos, [documentPaths](const FileInfo &fileInfo) {
|
||||
return documentPaths.contains(fileInfo.file);
|
||||
});
|
||||
}
|
||||
|
||||
static FileInfos fileInfosMatchingOpenedDocuments(const FileInfos &fileInfos)
|
||||
{
|
||||
// Note that (initially) suspended text documents are still IDocuments, not yet TextDocuments.
|
||||
return fileInfosMatchingDocuments(fileInfos, [](Core::IDocument *) { return true; });
|
||||
}
|
||||
|
||||
static FileInfos fileInfosMatchingEditedDocuments(const FileInfos &fileInfos)
|
||||
{
|
||||
return fileInfosMatchingDocuments(fileInfos, [](Core::IDocument *document) {
|
||||
if (auto textDocument = qobject_cast<TextEditor::TextDocument*>(document))
|
||||
return textDocument->document()->revision() > 1;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
FileInfoProviders ClangTool::fileInfoProviders(ProjectExplorer::Project *project,
|
||||
const FileInfos &allFileInfos)
|
||||
{
|
||||
ClangToolsProjectSettings *s = ClangToolsProjectSettingsManager::getSettings(project);
|
||||
static FileInfoSelection openedFilesSelection;
|
||||
static FileInfoSelection editeddFilesSelection;
|
||||
|
||||
return {
|
||||
{ClangTool::tr("All Files"),
|
||||
allFileInfos,
|
||||
FileInfoSelection{s->selectedDirs(), s->selectedFiles()},
|
||||
FileInfoProvider::Limited,
|
||||
[s](const FileInfoSelection &selection) {
|
||||
s->setSelectedDirs(selection.dirs);
|
||||
s->setSelectedFiles(selection.files);
|
||||
}},
|
||||
|
||||
{ClangTool::tr("Opened Files"),
|
||||
fileInfosMatchingOpenedDocuments(allFileInfos),
|
||||
openedFilesSelection,
|
||||
FileInfoProvider::All,
|
||||
[](const FileInfoSelection &selection) { openedFilesSelection = selection; }},
|
||||
|
||||
{ClangTool::tr("Edited Files"),
|
||||
fileInfosMatchingEditedDocuments(allFileInfos),
|
||||
editeddFilesSelection,
|
||||
FileInfoProvider::All,
|
||||
[](const FileInfoSelection &selection) { editeddFilesSelection = selection; }},
|
||||
};
|
||||
}
|
||||
|
||||
QSet<Diagnostic> ClangTool::diagnostics() const
|
||||
{
|
||||
return Utils::filtered(m_diagnosticModel->diagnostics(), [](const Diagnostic &diagnostic) {
|
||||
|
@@ -88,7 +88,7 @@ public:
|
||||
QString *errorMessage) const;
|
||||
|
||||
FileInfos collectFileInfos(ProjectExplorer::Project *project,
|
||||
FileSelection fileSelection) const;
|
||||
FileSelection fileSelection);
|
||||
|
||||
// For testing.
|
||||
QSet<Diagnostic> diagnostics() const;
|
||||
@@ -112,6 +112,9 @@ private:
|
||||
void initDiagnosticView();
|
||||
void loadDiagnosticsFromFiles();
|
||||
|
||||
FileInfoProviders fileInfoProviders(ProjectExplorer::Project *project,
|
||||
const FileInfos &allFileInfos);
|
||||
|
||||
ClangToolsDiagnosticModel *m_diagnosticModel = nullptr;
|
||||
QPointer<Debugger::DetailedErrorView> m_diagnosticView;
|
||||
|
||||
|
@@ -28,7 +28,6 @@
|
||||
#include <coreplugin/id.h>
|
||||
#include <cpptools/clangdiagnosticconfig.h>
|
||||
|
||||
#include <QVersionNumber>
|
||||
#include <QtGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
Reference in New Issue
Block a user