summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2021-08-30 10:58:08 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2021-09-01 14:53:58 +0000
commit284817fae6514701902ccdb834c2faa46462f2e8 (patch)
tree44a8c7d9813dc110b61c4639036366c7696bd7e9 /src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
parent3e1fa0f170d523971d2c3c12da15a6e291f56511 (diff)
downloadqt-creator-284817fae6514701902ccdb834c2faa46462f2e8.tar.gz
Merge CppTools into CppEditor
There was no proper separation of responsibilities between these plugins. In particular, CppTools had lots of editor-related functionality, so it's not clear why it was separated out in the first place. In fact, for a lot of code, it seemed quite arbitrary where it was put (just one example: switchHeaderSource() was in CppTools, wheras switchDeclarationDefinition() was in CppEditor). Merging the plugins will enable us to get rid of various convoluted pseudo-abstractions that were only introduced to keep up the artificial separation. Change-Id: Iafc3bce625b4794f6d4aa03df6cddc7f2d26716a Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/cpptools/clangdiagnosticconfigswidget.cpp')
-rw-r--r--src/plugins/cpptools/clangdiagnosticconfigswidget.cpp384
1 files changed, 0 insertions, 384 deletions
diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
deleted file mode 100644
index c41df55807..0000000000
--- a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
+++ /dev/null
@@ -1,384 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangdiagnosticconfigswidget.h"
-
-#include "cppcodemodelsettings.h"
-#include "ui_clangdiagnosticconfigswidget.h"
-#include "ui_clangbasechecks.h"
-
-#include <utils/executeondestruction.h>
-#include <utils/stringutils.h>
-#include <utils/treemodel.h>
-
-#include <QInputDialog>
-#include <QPushButton>
-
-namespace CppTools {
-
-class ConfigNode : public Utils::TreeItem
-{
-public:
- ConfigNode(const ClangDiagnosticConfig &config)
- : config(config)
- {}
-
- QVariant data(int, int role) const override
- {
- if (role == Qt::DisplayRole)
- return config.displayName();
- return QVariant();
- }
-
- ClangDiagnosticConfig config;
-};
-
-class GroupNode : public Utils::StaticTreeItem
-{
-public:
- GroupNode(const QString &text)
- : Utils::StaticTreeItem(text)
- {}
-
- Qt::ItemFlags flags(int) const final { return {}; }
- QVariant data(int column, int role) const final
- {
- if (role == Qt::ForegroundRole) {
- // Avoid disabled color.
- return QApplication::palette().color(QPalette::ColorGroup::Normal,
- QPalette::ColorRole::Text);
- }
- return Utils::StaticTreeItem::data(column, role);
- }
-};
-
-class ConfigsModel : public Utils::TreeModel<Utils::TreeItem, GroupNode, ConfigNode>
-{
- Q_OBJECT
-
-public:
- ConfigsModel(const ClangDiagnosticConfigs &configs)
- {
- m_builtinRoot = new GroupNode(tr("Built-in"));
- m_customRoot = new GroupNode(tr("Custom"));
- rootItem()->appendChild(m_builtinRoot);
- rootItem()->appendChild(m_customRoot);
-
- for (const ClangDiagnosticConfig &config : configs) {
- Utils::TreeItem *parent = config.isReadOnly() ? m_builtinRoot : m_customRoot;
- parent->appendChild(new ConfigNode(config));
- }
- }
-
- int customConfigsCount() const { return m_customRoot->childCount(); }
- QModelIndex fallbackConfigIndex() const { return m_builtinRoot->lastChild()->index(); }
-
- ClangDiagnosticConfigs configs() const
- {
- ClangDiagnosticConfigs configs;
- forItemsAtLevel<2>([&configs](const ConfigNode *node) {
- configs << node->config;
- });
- return configs;
- }
-
- void appendCustomConfig(const ClangDiagnosticConfig &config)
- {
- m_customRoot->appendChild(new ConfigNode(config));
- }
-
- void removeConfig(const Utils::Id &id)
- {
- ConfigNode *node = itemForConfigId(id);
- node->parent()->removeChildAt(node->indexInParent());
- }
-
- ConfigNode *itemForConfigId(const Utils::Id &id) const
- {
- return findItemAtLevel<2>([id](const ConfigNode *node) {
- return node->config.id() == id;
- });
- }
-
-private:
- Utils::TreeItem *m_builtinRoot = nullptr;
- Utils::TreeItem *m_customRoot = nullptr;
-};
-
-ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget(const ClangDiagnosticConfigs &configs,
- const Utils::Id &configToSelect,
- QWidget *parent)
- : QWidget(parent)
- , m_ui(new Ui::ClangDiagnosticConfigsWidget)
- , m_configsModel(new ConfigsModel(configs))
-{
- m_ui->setupUi(this);
- m_ui->configsView->setHeaderHidden(true);
- m_ui->configsView->setUniformRowHeights(true);
- m_ui->configsView->setRootIsDecorated(false);
- m_ui->configsView->setModel(m_configsModel);
- m_ui->configsView->setCurrentIndex(m_configsModel->itemForConfigId(configToSelect)->index());
- m_ui->configsView->setItemsExpandable(false);
- m_ui->configsView->expandAll();
- connect(m_ui->configsView->selectionModel(),
- &QItemSelectionModel::currentChanged,
- this,
- &ClangDiagnosticConfigsWidget::sync);
-
- m_clangBaseChecks = std::make_unique<CppTools::Ui::ClangBaseChecks>();
- m_clangBaseChecksWidget = new QWidget();
- m_clangBaseChecks->setupUi(m_clangBaseChecksWidget);
-
- m_ui->tabWidget->addTab(m_clangBaseChecksWidget, tr("Clang Warnings"));
- m_ui->tabWidget->setCurrentIndex(0);
-
- connect(m_ui->copyButton, &QPushButton::clicked,
- this, &ClangDiagnosticConfigsWidget::onCopyButtonClicked);
- connect(m_ui->renameButton, &QPushButton::clicked,
- this, &ClangDiagnosticConfigsWidget::onRenameButtonClicked);
- connect(m_ui->removeButton, &QPushButton::clicked,
- this, &ClangDiagnosticConfigsWidget::onRemoveButtonClicked);
- connectClangOnlyOptionsChanged();
-}
-
-ClangDiagnosticConfigsWidget::~ClangDiagnosticConfigsWidget()
-{
- delete m_ui;
-}
-
-void ClangDiagnosticConfigsWidget::onCopyButtonClicked()
-{
- const ClangDiagnosticConfig &config = currentConfig();
- bool dialogAccepted = false;
- const QString newName = QInputDialog::getText(this,
- tr("Copy Diagnostic Configuration"),
- tr("Diagnostic configuration name:"),
- QLineEdit::Normal,
- tr("%1 (Copy)").arg(config.displayName()),
- &dialogAccepted);
- if (dialogAccepted) {
- const ClangDiagnosticConfig customConfig
- = ClangDiagnosticConfigsModel::createCustomConfig(config, newName);
-
- m_configsModel->appendCustomConfig(customConfig);
- m_ui->configsView->setCurrentIndex(
- m_configsModel->itemForConfigId(customConfig.id())->index());
- sync();
- m_clangBaseChecks->diagnosticOptionsTextEdit->setFocus();
- }
-}
-
-void ClangDiagnosticConfigsWidget::onRenameButtonClicked()
-{
- const ClangDiagnosticConfig &config = currentConfig();
-
- bool dialogAccepted = false;
- const QString newName = QInputDialog::getText(this,
- tr("Rename Diagnostic Configuration"),
- tr("New name:"),
- QLineEdit::Normal,
- config.displayName(),
- &dialogAccepted);
- if (dialogAccepted) {
- ConfigNode *configNode = m_configsModel->itemForConfigId(config.id());
- configNode->config.setDisplayName(newName);
- }
-}
-
-const ClangDiagnosticConfig ClangDiagnosticConfigsWidget::currentConfig() const
-{
- Utils::TreeItem *item = m_configsModel->itemForIndex(m_ui->configsView->currentIndex());
- return static_cast<ConfigNode *>(item)->config;
-}
-
-void ClangDiagnosticConfigsWidget::onRemoveButtonClicked()
-{
- const Utils::Id configToRemove = currentConfig().id();
- if (m_configsModel->customConfigsCount() == 1)
- m_ui->configsView->setCurrentIndex(m_configsModel->fallbackConfigIndex());
- m_configsModel->removeConfig(configToRemove);
- sync();
-}
-
-static bool isAcceptedWarningOption(const QString &option)
-{
- return option == "-w"
- || option == "-pedantic"
- || option == "-pedantic-errors";
-}
-
-// Reference:
-// https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
-// https://clang.llvm.org/docs/DiagnosticsReference.html
-static bool isValidOption(const QString &option)
-{
- if (option == "-Werror")
- return false; // Avoid errors due to unknown or misspelled warnings.
- return option.startsWith("-W") || isAcceptedWarningOption(option);
-}
-
-static QString validateDiagnosticOptions(const QStringList &options)
-{
- // This is handy for testing, allow disabling validation.
- if (qEnvironmentVariableIntValue("QTC_CLANG_NO_DIAGNOSTIC_CHECK"))
- return QString();
-
- for (const QString &option : options) {
- if (!isValidOption(option))
- return ClangDiagnosticConfigsWidget::tr("Option \"%1\" is invalid.").arg(option);
- }
-
- return QString();
-}
-
-static QStringList normalizeDiagnosticInputOptions(const QString &options)
-{
- return options.simplified().split(QLatin1Char(' '), Qt::SkipEmptyParts);
-}
-
-void ClangDiagnosticConfigsWidget::onClangOnlyOptionsChanged()
-{
- const bool useBuildSystemWarnings = m_clangBaseChecks->useFlagsFromBuildSystemCheckBox
- ->isChecked();
-
- // Clean up options input
- const QString diagnosticOptions = m_clangBaseChecks->diagnosticOptionsTextEdit->document()
- ->toPlainText();
- const QStringList normalizedOptions = normalizeDiagnosticInputOptions(diagnosticOptions);
-
- // Validate options input
- const QString errorMessage = validateDiagnosticOptions(normalizedOptions);
- updateValidityWidgets(errorMessage);
- if (!errorMessage.isEmpty()) {
- // Remember the entered options in case the user will switch back.
- m_notAcceptedOptions.insert(currentConfig().id(), diagnosticOptions);
- return;
- }
- m_notAcceptedOptions.remove(currentConfig().id());
-
- // Commit valid changes
- ClangDiagnosticConfig updatedConfig = currentConfig();
- updatedConfig.setClangOptions(normalizedOptions);
- updatedConfig.setUseBuildSystemWarnings(useBuildSystemWarnings);
- updateConfig(updatedConfig);
-}
-
-void ClangDiagnosticConfigsWidget::sync()
-{
- if (!m_ui->configsView->currentIndex().isValid())
- return;
-
- disconnectClangOnlyOptionsChanged();
- Utils::ExecuteOnDestruction e([this]() { connectClangOnlyOptionsChanged(); });
-
- // Update main button row
- const ClangDiagnosticConfig &config = currentConfig();
- m_ui->removeButton->setEnabled(!config.isReadOnly());
- m_ui->renameButton->setEnabled(!config.isReadOnly());
-
- // Update check box
- m_clangBaseChecks->useFlagsFromBuildSystemCheckBox->setChecked(config.useBuildSystemWarnings());
-
- // Update Text Edit
- const QString options = m_notAcceptedOptions.contains(config.id())
- ? m_notAcceptedOptions.value(config.id())
- : config.clangOptions().join(QLatin1Char(' '));
- setDiagnosticOptions(options);
- m_clangBaseChecksWidget->setEnabled(!config.isReadOnly());
-
- if (config.isReadOnly()) {
- m_ui->infoLabel->setType(Utils::InfoLabel::Information);
- m_ui->infoLabel->setText(tr("Copy this configuration to customize it."));
- m_ui->infoLabel->setFilled(false);
- }
-
- syncExtraWidgets(config);
-}
-
-void ClangDiagnosticConfigsWidget::updateConfig(const ClangDiagnosticConfig &config)
-{
- m_configsModel->itemForConfigId(config.id())->config = config;
-}
-
-void ClangDiagnosticConfigsWidget::setDiagnosticOptions(const QString &options)
-{
- if (options != m_clangBaseChecks->diagnosticOptionsTextEdit->document()->toPlainText())
- m_clangBaseChecks->diagnosticOptionsTextEdit->document()->setPlainText(options);
-
- const QString errorMessage
- = validateDiagnosticOptions(normalizeDiagnosticInputOptions(options));
- updateValidityWidgets(errorMessage);
-}
-
-void ClangDiagnosticConfigsWidget::updateValidityWidgets(const QString &errorMessage)
-{
- if (errorMessage.isEmpty()) {
- m_ui->infoLabel->setType(Utils::InfoLabel::Information);
- m_ui->infoLabel->setText(tr("Configuration passes sanity checks."));
- m_ui->infoLabel->setFilled(false);
- } else {
- m_ui->infoLabel->setType(Utils::InfoLabel::Error);
- m_ui->infoLabel->setText(tr("%1").arg(errorMessage));
- m_ui->infoLabel->setFilled(true);
- }
-}
-
-void ClangDiagnosticConfigsWidget::connectClangOnlyOptionsChanged()
-{
- connect(m_clangBaseChecks->useFlagsFromBuildSystemCheckBox,
- &QCheckBox::stateChanged,
- this,
- &ClangDiagnosticConfigsWidget::onClangOnlyOptionsChanged);
- connect(m_clangBaseChecks->diagnosticOptionsTextEdit->document(),
- &QTextDocument::contentsChanged,
- this,
- &ClangDiagnosticConfigsWidget::onClangOnlyOptionsChanged);
-}
-
-void ClangDiagnosticConfigsWidget::disconnectClangOnlyOptionsChanged()
-{
- disconnect(m_clangBaseChecks->useFlagsFromBuildSystemCheckBox,
- &QCheckBox::stateChanged,
- this,
- &ClangDiagnosticConfigsWidget::onClangOnlyOptionsChanged);
- disconnect(m_clangBaseChecks->diagnosticOptionsTextEdit->document(),
- &QTextDocument::contentsChanged,
- this,
- &ClangDiagnosticConfigsWidget::onClangOnlyOptionsChanged);
-}
-
-ClangDiagnosticConfigs ClangDiagnosticConfigsWidget::configs() const
-{
- return m_configsModel->configs();
-}
-
-QTabWidget *ClangDiagnosticConfigsWidget::tabWidget() const
-{
- return m_ui->tabWidget;
-}
-
-} // CppTools namespace
-
-#include "clangdiagnosticconfigswidget.moc"