forked from qt-creator/qt-creator
ClangTools: Add "edit as string" feature also for clazy
Fixes: QTCREATORBUG-24846 Change-Id: Id9931c0539ff1e03ab9cac7fb9b76f9694250536 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -116,6 +116,7 @@ public:
|
|||||||
QListView *topicsView;
|
QListView *topicsView;
|
||||||
QGroupBox *checksGroupBox;
|
QGroupBox *checksGroupBox;
|
||||||
QCheckBox *enableLowerLevelsCheckBox;
|
QCheckBox *enableLowerLevelsCheckBox;
|
||||||
|
QPushButton plainTextEditButton;
|
||||||
QTreeView *checksView;
|
QTreeView *checksView;
|
||||||
|
|
||||||
ClazyChecksWidget()
|
ClazyChecksWidget()
|
||||||
@@ -146,6 +147,7 @@ public:
|
|||||||
enableLowerLevelsCheckBox->setToolTip(Tr::tr("When enabling a level explicitly, "
|
enableLowerLevelsCheckBox->setToolTip(Tr::tr("When enabling a level explicitly, "
|
||||||
"also enable lower levels (Clazy semantic)."));
|
"also enable lower levels (Clazy semantic)."));
|
||||||
|
|
||||||
|
plainTextEditButton.setText(Tr::tr("Edit Checks as String..."));
|
||||||
checksView = new QTreeView;
|
checksView = new QTreeView;
|
||||||
|
|
||||||
auto invalidExecutablePage = new QWidget;
|
auto invalidExecutablePage = new QWidget;
|
||||||
@@ -183,6 +185,7 @@ public:
|
|||||||
|
|
||||||
Column {
|
Column {
|
||||||
enableLowerLevelsCheckBox,
|
enableLowerLevelsCheckBox,
|
||||||
|
&plainTextEditButton,
|
||||||
checksView,
|
checksView,
|
||||||
}.attachTo(checksGroupBox);
|
}.attachTo(checksGroupBox);
|
||||||
|
|
||||||
@@ -489,8 +492,33 @@ public:
|
|||||||
return indexForName(QModelIndex(), name);
|
return indexForName(QModelIndex(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
void selectChecks(const QString &checks)
|
||||||
bool m_enabled = true;
|
{
|
||||||
|
m_root->checked = Qt::Unchecked;
|
||||||
|
propagateDown(index(0, 0, QModelIndex()));
|
||||||
|
|
||||||
|
QStringList checksList = checks.simplified().remove(" ")
|
||||||
|
.split(",", Qt::SkipEmptyParts);
|
||||||
|
|
||||||
|
for (QString &check : checksList) {
|
||||||
|
Qt::CheckState state;
|
||||||
|
if (check.startsWith("-")) {
|
||||||
|
check = check.right(check.length() - 1);
|
||||||
|
state = Qt::Unchecked;
|
||||||
|
} else {
|
||||||
|
state = Qt::Checked;
|
||||||
|
}
|
||||||
|
const QModelIndex index = indexForCheck(check);
|
||||||
|
if (!index.isValid())
|
||||||
|
continue;
|
||||||
|
auto *node = static_cast<ProjectExplorer::Tree *>(index.internalPointer());
|
||||||
|
node->checked = state;
|
||||||
|
propagateUp(index);
|
||||||
|
propagateDown(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString selectedChecks() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QModelIndex indexForName(const QModelIndex ¤t, const QString &name) const
|
QModelIndex indexForName(const QModelIndex ¤t, const QString &name) const
|
||||||
@@ -518,6 +546,10 @@ private:
|
|||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual QModelIndex indexForCheck(const QString &check) const { return indexForName(check); }
|
||||||
|
|
||||||
|
bool m_enabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void openUrl(QAbstractItemModel *model, const QModelIndex &index)
|
static void openUrl(QAbstractItemModel *model, const QModelIndex &index)
|
||||||
@@ -539,39 +571,13 @@ public:
|
|||||||
buildTree(nullptr, m_root, ClangTidyPrefixTree::Node::fromCheckList(supportedChecks));
|
buildTree(nullptr, m_root, ClangTidyPrefixTree::Node::fromCheckList(supportedChecks));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString selectedChecks() const
|
QString selectedChecks() const override
|
||||||
{
|
{
|
||||||
QString checks;
|
QString checks;
|
||||||
collectChecks(m_root, checks);
|
collectChecks(m_root, checks);
|
||||||
return "-*" + checks;
|
return "-*" + checks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectChecks(const QString &checks)
|
|
||||||
{
|
|
||||||
m_root->checked = Qt::Unchecked;
|
|
||||||
propagateDown(index(0, 0, QModelIndex()));
|
|
||||||
|
|
||||||
QStringList checksList = checks.simplified().remove(" ")
|
|
||||||
.split(",", Qt::SkipEmptyParts);
|
|
||||||
|
|
||||||
for (QString &check : checksList) {
|
|
||||||
Qt::CheckState state;
|
|
||||||
if (check.startsWith("-")) {
|
|
||||||
check = check.right(check.length() - 1);
|
|
||||||
state = Qt::Unchecked;
|
|
||||||
} else {
|
|
||||||
state = Qt::Checked;
|
|
||||||
}
|
|
||||||
const QModelIndex index = indexForCheck(check);
|
|
||||||
if (!index.isValid())
|
|
||||||
continue;
|
|
||||||
auto *node = static_cast<ProjectExplorer::Tree *>(index.internalPointer());
|
|
||||||
node->checked = state;
|
|
||||||
propagateUp(index);
|
|
||||||
propagateDown(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant data(const QModelIndex &fullIndex, int role = Qt::DisplayRole) const final
|
QVariant data(const QModelIndex &fullIndex, int role = Qt::DisplayRole) const final
|
||||||
{
|
{
|
||||||
if (!fullIndex.isValid() || role == Qt::DecorationRole)
|
if (!fullIndex.isValid() || role == Qt::DecorationRole)
|
||||||
@@ -614,7 +620,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
int columnCount(const QModelIndex &) const final { return 3; }
|
int columnCount(const QModelIndex &) const final { return 3; }
|
||||||
|
|
||||||
QModelIndex indexForCheck(const QString &check) const {
|
QModelIndex indexForCheck(const QString &check) const override {
|
||||||
if (check == "*")
|
if (check == "*")
|
||||||
return index(0, 0, QModelIndex());
|
return index(0, 0, QModelIndex());
|
||||||
|
|
||||||
@@ -781,6 +787,8 @@ private:
|
|||||||
return ProjectExplorer::SelectableFilesModel::data(index, role);
|
return ProjectExplorer::SelectableFilesModel::data(index, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString selectedChecks() const override { return enabledChecks().join(','); }
|
||||||
|
|
||||||
static QString levelDescription(int level)
|
static QString levelDescription(int level)
|
||||||
{
|
{
|
||||||
switch (level) {
|
switch (level) {
|
||||||
@@ -840,6 +848,7 @@ private:
|
|||||||
if (root->checked == Qt::Unchecked)
|
if (root->checked == Qt::Unchecked)
|
||||||
return;
|
return;
|
||||||
if (root->checked == Qt::Checked && !root->isDir) {
|
if (root->checked == Qt::Checked && !root->isDir) {
|
||||||
|
// TODO: Use shortcuts: "level0", "level1", "level2"
|
||||||
checks.append(root->name);
|
checks.append(root->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1041,46 +1050,10 @@ DiagnosticConfigsWidget::DiagnosticConfigsWidget(const ClangDiagnosticConfigs &c
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(m_tidyChecks->plainTextEditButton, &QPushButton::clicked, this, [this] {
|
connect(m_tidyChecks->plainTextEditButton, &QPushButton::clicked, this, [this] {
|
||||||
const bool readOnly = currentConfig().isReadOnly();
|
handleChecksAsStringsButtonClicked(m_tidyTreeModel.get());
|
||||||
|
});
|
||||||
QDialog dialog;
|
connect(&m_clazyChecks->plainTextEditButton, &QPushButton::clicked, this, [this] {
|
||||||
dialog.setWindowTitle(Tr::tr("Checks"));
|
handleChecksAsStringsButtonClicked(m_clazyTreeModel.get());
|
||||||
|
|
||||||
const QString initialChecks = m_tidyTreeModel->selectedChecks();
|
|
||||||
|
|
||||||
auto textEdit = new QTextEdit(&dialog);
|
|
||||||
textEdit->setReadOnly(readOnly);
|
|
||||||
textEdit->setPlainText(initialChecks);
|
|
||||||
|
|
||||||
auto buttonsBox = new QDialogButtonBox(QDialogButtonBox::Ok
|
|
||||||
| (readOnly ? QDialogButtonBox::NoButton
|
|
||||||
: QDialogButtonBox::Cancel));
|
|
||||||
|
|
||||||
using namespace Layouting;
|
|
||||||
|
|
||||||
Column {
|
|
||||||
textEdit,
|
|
||||||
buttonsBox
|
|
||||||
}.attachTo(&dialog);
|
|
||||||
|
|
||||||
QObject::connect(&dialog, &QDialog::accepted, this, [=, &initialChecks] {
|
|
||||||
const QString updatedChecks = textEdit->toPlainText();
|
|
||||||
if (updatedChecks == initialChecks)
|
|
||||||
return;
|
|
||||||
|
|
||||||
disconnectClangTidyItemChanged();
|
|
||||||
|
|
||||||
// Also throws away invalid options.
|
|
||||||
m_tidyTreeModel->selectChecks(updatedChecks);
|
|
||||||
onClangTidyTreeChanged();
|
|
||||||
|
|
||||||
connectClangTidyItemChanged();
|
|
||||||
});
|
|
||||||
|
|
||||||
QObject::connect(buttonsBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
|
||||||
QObject::connect(buttonsBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
|
||||||
|
|
||||||
dialog.exec();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connectClangTidyItemChanged();
|
connectClangTidyItemChanged();
|
||||||
@@ -1153,6 +1126,8 @@ void DiagnosticConfigsWidget::syncClazyWidgets(const ClangDiagnosticConfig &conf
|
|||||||
m_clazyChecks->topicsView->clearSelection();
|
m_clazyChecks->topicsView->clearSelection();
|
||||||
m_clazyChecks->topicsView->setEnabled(enabled);
|
m_clazyChecks->topicsView->setEnabled(enabled);
|
||||||
m_clazyTreeModel->setEnabled(enabled);
|
m_clazyTreeModel->setEnabled(enabled);
|
||||||
|
m_clazyChecks->plainTextEditButton.setText(enabled ? Tr::tr("Edit Checks as String...")
|
||||||
|
: Tr::tr("View Checks as String..."));
|
||||||
|
|
||||||
connectClazyItemChanged();
|
connectClazyItemChanged();
|
||||||
}
|
}
|
||||||
@@ -1196,6 +1171,50 @@ void DiagnosticConfigsWidget::disconnectClazyItemChanged()
|
|||||||
this, &DiagnosticConfigsWidget::onClazyTreeChanged);
|
this, &DiagnosticConfigsWidget::onClazyTreeChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiagnosticConfigsWidget::handleChecksAsStringsButtonClicked(BaseChecksTreeModel *model)
|
||||||
|
{
|
||||||
|
const bool readOnly = currentConfig().isReadOnly();
|
||||||
|
|
||||||
|
QDialog dialog;
|
||||||
|
dialog.setWindowTitle(Tr::tr("Checks"));
|
||||||
|
|
||||||
|
const QString initialChecks = model->selectedChecks();
|
||||||
|
|
||||||
|
auto textEdit = new QTextEdit(&dialog);
|
||||||
|
textEdit->setReadOnly(readOnly);
|
||||||
|
textEdit->setPlainText(initialChecks);
|
||||||
|
|
||||||
|
auto buttonsBox = new QDialogButtonBox(QDialogButtonBox::Ok
|
||||||
|
| (readOnly ? QDialogButtonBox::NoButton
|
||||||
|
: QDialogButtonBox::Cancel));
|
||||||
|
|
||||||
|
using namespace Layouting;
|
||||||
|
|
||||||
|
Column {
|
||||||
|
textEdit,
|
||||||
|
buttonsBox
|
||||||
|
}.attachTo(&dialog);
|
||||||
|
|
||||||
|
QObject::connect(&dialog, &QDialog::accepted, this, [=, &initialChecks] {
|
||||||
|
const QString updatedChecks = textEdit->toPlainText();
|
||||||
|
if (updatedChecks == initialChecks)
|
||||||
|
return;
|
||||||
|
|
||||||
|
disconnectClangTidyItemChanged();
|
||||||
|
|
||||||
|
// Also throws away invalid options.
|
||||||
|
model->selectChecks(updatedChecks);
|
||||||
|
onClangTidyTreeChanged();
|
||||||
|
|
||||||
|
connectClangTidyItemChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
QObject::connect(buttonsBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||||
|
QObject::connect(buttonsBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||||
|
|
||||||
|
dialog.exec();
|
||||||
|
}
|
||||||
|
|
||||||
void DiagnosticConfigsWidget::onClangTidyTreeChanged()
|
void DiagnosticConfigsWidget::onClangTidyTreeChanged()
|
||||||
{
|
{
|
||||||
ClangDiagnosticConfig config = currentConfig();
|
ClangDiagnosticConfig config = currentConfig();
|
||||||
|
@@ -15,6 +15,7 @@ class ClazyChecksSortFilterModel;
|
|||||||
class ClazyChecksTreeModel;
|
class ClazyChecksTreeModel;
|
||||||
class ClazyChecksWidget;
|
class ClazyChecksWidget;
|
||||||
class Diagnostic;
|
class Diagnostic;
|
||||||
|
class BaseChecksTreeModel;
|
||||||
class TidyChecksTreeModel;
|
class TidyChecksTreeModel;
|
||||||
class TidyChecksWidget;
|
class TidyChecksWidget;
|
||||||
|
|
||||||
@@ -50,7 +51,8 @@ private:
|
|||||||
void connectClazyItemChanged();
|
void connectClazyItemChanged();
|
||||||
void disconnectClazyItemChanged();
|
void disconnectClazyItemChanged();
|
||||||
|
|
||||||
private:
|
void handleChecksAsStringsButtonClicked(BaseChecksTreeModel *model);
|
||||||
|
|
||||||
// Clang-Tidy
|
// Clang-Tidy
|
||||||
TidyChecksWidget *m_tidyChecks = nullptr;
|
TidyChecksWidget *m_tidyChecks = nullptr;
|
||||||
std::unique_ptr<TidyChecksTreeModel> m_tidyTreeModel;
|
std::unique_ptr<TidyChecksTreeModel> m_tidyTreeModel;
|
||||||
|
Reference in New Issue
Block a user