diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp
index faaf6d937ff..27192a67f64 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.cpp
+++ b/src/plugins/clangformat/clangformatconfigwidget.cpp
@@ -59,6 +59,24 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *proje
{
m_ui->setupUi(this);
+ m_preview = new TextEditor::SnippetEditorWidget(this);
+ m_ui->horizontalLayout_2->addWidget(m_preview);
+ if (m_project) {
+ m_ui->applyButton->show();
+ hideGlobalCheckboxes();
+ m_ui->overrideDefault->setChecked(
+ m_project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool());
+ } else {
+ m_ui->applyButton->hide();
+ showGlobalCheckboxes();
+ m_ui->overrideDefault->setChecked(ClangFormatSettings::instance().overrideDefaultFile());
+ }
+
+ connect(m_ui->overrideDefault, &QCheckBox::toggled, this, [this](bool checked) {
+ if (checked)
+ createStyleFileIfNeeded(!m_project);
+ initialize();
+ });
initialize();
}
@@ -81,15 +99,18 @@ void ClangFormatConfigWidget::showGlobalCheckboxes()
m_ui->formatOnSave->show();
}
+static bool projectConfigExists()
+{
+ return Utils::FileName::fromString(Core::ICore::userResourcePath())
+ .appendPath(currentProjectUniqueId())
+ .appendPath((Constants::SETTINGS_FILE_NAME))
+ .exists();
+}
+
void ClangFormatConfigWidget::initialize()
{
- m_ui->projectHasClangFormat->show();
- m_ui->clangFormatOptionsTable->show();
- m_ui->applyButton->show();
- hideGlobalCheckboxes();
+ m_ui->projectHasClangFormat->hide();
- m_preview = new TextEditor::SnippetEditorWidget(this);
- m_ui->horizontalLayout_2->addWidget(m_preview);
m_preview->setPlainText(QLatin1String(CppTools::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
m_preview->textDocument()->setIndenter(new ClangFormatIndenter(m_preview->document()));
m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
@@ -103,21 +124,15 @@ void ClangFormatConfigWidget::initialize()
if (lastItem->spacerItem())
m_ui->verticalLayout->removeItem(lastItem);
- if (m_project
- && !m_project->projectDirectory().appendPath(Constants::SETTINGS_FILE_NAME).exists()) {
- m_ui->projectHasClangFormat->setText(tr("No .clang-format file for the project."));
+ if (!m_ui->overrideDefault->isChecked()) {
m_ui->clangFormatOptionsTable->hide();
- m_ui->applyButton->hide();
+ m_preview->hide();
m_ui->verticalLayout->addStretch(1);
-
- connect(m_ui->createFileButton, &QPushButton::clicked, this, [this]() {
- createStyleFileIfNeeded(false);
- initialize();
- });
return;
}
- m_ui->createFileButton->hide();
+ m_ui->clangFormatOptionsTable->show();
+ m_preview->show();
Utils::FileName fileName;
if (m_project) {
@@ -126,19 +141,13 @@ void ClangFormatConfigWidget::initialize()
fileName = m_project->projectFilePath().appendPath("snippet.cpp");
} else {
const Project *currentProject = SessionManager::startupProject();
- if (!currentProject
- || !currentProject->projectDirectory()
- .appendPath(Constants::SETTINGS_FILE_NAME)
- .exists()) {
+ if (!currentProject || !projectConfigExists()) {
m_ui->projectHasClangFormat->hide();
} else {
m_ui->projectHasClangFormat->setText(
- tr("Current project has its own .clang-format file "
+ tr("Current project has its own overridden .clang-format file "
"and can be configured in Projects > Code Style > C++."));
}
- createStyleFileIfNeeded(true);
- showGlobalCheckboxes();
- m_ui->applyButton->hide();
fileName = Utils::FileName::fromString(Core::ICore::userResourcePath())
.appendPath("snippet.cpp");
}
@@ -160,7 +169,7 @@ void ClangFormatConfigWidget::fillTable()
{
clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle();
- std::string configText = clang::format::configurationAsText(style);
+ const std::string configText = clang::format::configurationAsText(style);
m_ui->clangFormatOptionsTable->setPlainText(QString::fromStdString(configText));
}
@@ -168,13 +177,16 @@ ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
void ClangFormatConfigWidget::apply()
{
+ ClangFormatSettings &settings = ClangFormatSettings::instance();
if (!m_project) {
- ClangFormatSettings &settings = ClangFormatSettings::instance();
settings.setFormatCodeInsteadOfIndent(m_ui->formatAlways->isChecked());
settings.setFormatWhileTyping(m_ui->formatWhileTyping->isChecked());
settings.setFormatOnSave(m_ui->formatOnSave->isChecked());
- settings.write();
+ settings.setOverrideDefaultFile(m_ui->overrideDefault->isChecked());
+ } else {
+ m_project->setNamedSettings(Constants::OVERRIDE_FILE_ID, m_ui->overrideDefault->isChecked());
}
+ settings.write();
const QString text = m_ui->clangFormatOptionsTable->toPlainText();
clang::format::FormatStyle style;
@@ -184,16 +196,18 @@ void ClangFormatConfigWidget::apply()
QMessageBox::warning(this,
tr("Error in ClangFormat configuration"),
QString::fromStdString(error.message()));
- fillTable();
- updatePreview();
+ if (m_ui->overrideDefault->isChecked()) {
+ fillTable();
+ updatePreview();
+ }
return;
}
- QString filePath;
+ QString filePath = Core::ICore::userResourcePath();
if (m_project)
- filePath = m_project->projectDirectory().appendPath(Constants::SETTINGS_FILE_NAME).toString();
- else
- filePath = Core::ICore::userResourcePath() + "/" + Constants::SETTINGS_FILE_NAME;
+ filePath += "/" + currentProjectUniqueId();
+ filePath += "/" + QLatin1String(Constants::SETTINGS_FILE_NAME);
+
QFile file(filePath);
if (!file.open(QFile::WriteOnly))
return;
@@ -201,7 +215,8 @@ void ClangFormatConfigWidget::apply()
file.write(text.toUtf8());
file.close();
- updatePreview();
+ if (m_ui->overrideDefault->isChecked())
+ updatePreview();
}
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatconfigwidget.ui b/src/plugins/clangformat/clangformatconfigwidget.ui
index 41e40ef1fdc..c8225981f59 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.ui
+++ b/src/plugins/clangformat/clangformatconfigwidget.ui
@@ -54,6 +54,13 @@
+ -
+
+
+ Override Clang Format configuration file
+
+
+
-
-
@@ -63,13 +70,6 @@
-
-
-
-
-
- Create Clang Format Configuration File
-
-
-
-
diff --git a/src/plugins/clangformat/clangformatconstants.h b/src/plugins/clangformat/clangformatconstants.h
index 8b7cbcf9bd2..65ea9b6e81f 100644
--- a/src/plugins/clangformat/clangformatconstants.h
+++ b/src/plugins/clangformat/clangformatconstants.h
@@ -34,5 +34,6 @@ static const char SETTINGS_ID[] = "ClangFormat";
static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent";
static const char FORMAT_WHILE_TYPING_ID[] = "ClangFormat.FormatWhileTyping";
static const char FORMAT_CODE_ON_SAVE_ID[] = "ClangFormat.FormatCodeOnSave";
+static const char OVERRIDE_FILE_ID[] = "ClangFormat.OverrideFile";
} // namespace Constants
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp
index 42cedb7b6c9..381762ee7f2 100644
--- a/src/plugins/clangformat/clangformatindenter.cpp
+++ b/src/plugins/clangformat/clangformatindenter.cpp
@@ -57,7 +57,7 @@ bool ClangFormatIndenter::formatWhileTyping() const
Utils::optional ClangFormatIndenter::tabSettings() const
{
- FormatStyle style = currentProjectStyle();
+ FormatStyle style = styleForFile();
TabSettings tabSettings;
switch (style.UseTab) {
diff --git a/src/plugins/clangformat/clangformatsettings.cpp b/src/plugins/clangformat/clangformatsettings.cpp
index 8be2b3cefee..8f70130ae3a 100644
--- a/src/plugins/clangformat/clangformatsettings.cpp
+++ b/src/plugins/clangformat/clangformatsettings.cpp
@@ -46,6 +46,8 @@ ClangFormatSettings::ClangFormatSettings()
.toBool();
m_formatOnSave = settings->value(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), false)
.toBool();
+ m_overrideDefaultFile = settings->value(QLatin1String(Constants::OVERRIDE_FILE_ID), false)
+ .toBool();
settings->endGroup();
}
@@ -57,6 +59,7 @@ void ClangFormatSettings::write() const
m_formatCodeInsteadOfIndent);
settings->setValue(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), m_formatWhileTyping);
settings->setValue(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), m_formatOnSave);
+ settings->setValue(QLatin1String(Constants::OVERRIDE_FILE_ID), m_overrideDefaultFile);
settings->endGroup();
}
@@ -90,4 +93,14 @@ bool ClangFormatSettings::formatOnSave() const
return m_formatOnSave;
}
+void ClangFormatSettings::setOverrideDefaultFile(bool enable)
+{
+ m_overrideDefaultFile = enable;
+}
+
+bool ClangFormatSettings::overrideDefaultFile() const
+{
+ return m_overrideDefaultFile;
+}
+
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatsettings.h b/src/plugins/clangformat/clangformatsettings.h
index 0ea9ed9747e..9344cf34a96 100644
--- a/src/plugins/clangformat/clangformatsettings.h
+++ b/src/plugins/clangformat/clangformatsettings.h
@@ -25,6 +25,8 @@
#pragma once
+#include
+
namespace ClangFormat {
class ClangFormatSettings
@@ -43,10 +45,14 @@ public:
void setFormatOnSave(bool enable);
bool formatOnSave() const;
+
+ void setOverrideDefaultFile(bool enable);
+ bool overrideDefaultFile() const;
private:
bool m_formatCodeInsteadOfIndent = false;
bool m_formatWhileTyping = false;
bool m_formatOnSave = false;
+ bool m_overrideDefaultFile = false;
};
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp
index babe94da24f..36bcf2f97d0 100644
--- a/src/plugins/clangformat/clangformatutils.cpp
+++ b/src/plugins/clangformat/clangformatutils.cpp
@@ -26,6 +26,7 @@
#include "clangformatutils.h"
#include "clangformatconstants.h"
+#include "clangformatsettings.h"
#include
#include
@@ -33,6 +34,8 @@
#include
#include
+#include
+
using namespace clang;
using namespace format;
using namespace llvm;
@@ -92,13 +95,26 @@ static void applyCppCodeStyleSettings(clang::format::FormatStyle &style,
: - static_cast(style.IndentWidth);
}
-static Utils::FileName projectPath()
+static bool useGlobalOverriddenSettings()
+{
+ return ClangFormatSettings::instance().overrideDefaultFile();
+}
+
+QString currentProjectUniqueId()
{
const Project *project = SessionManager::startupProject();
- if (project)
- return project->projectDirectory();
+ if (!project)
+ return QString();
- return Utils::FileName();
+ return QString::fromUtf8(QCryptographicHash::hash(project->projectFilePath().toString().toUtf8(),
+ QCryptographicHash::Md5)
+ .toHex(0));
+}
+
+static bool useProjectOverriddenSettings()
+{
+ const Project *project = SessionManager::startupProject();
+ return project ? project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool() : false;
}
static Utils::FileName globalPath()
@@ -106,25 +122,40 @@ static Utils::FileName globalPath()
return Utils::FileName::fromString(Core::ICore::userResourcePath());
}
-static QString configForFile(Utils::FileName fileName)
+static Utils::FileName projectPath()
{
- Utils::FileName topProjectPath = projectPath();
- if (topProjectPath.isEmpty())
- return QString();
+ const Project *project = SessionManager::startupProject();
+ if (project)
+ return globalPath().appendPath("clang-format").appendPath(currentProjectUniqueId());
- QDir projectDir(fileName.parentDir().toString());
- while (!projectDir.exists(Constants::SETTINGS_FILE_NAME)
- && !projectDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) {
- if (projectDir.path() == topProjectPath.toString()
- || !Utils::FileName::fromString(projectDir.path()).isChildOf(topProjectPath)
- || !projectDir.cdUp()) {
- return QString();
- }
+ return Utils::FileName();
+}
+
+static QString configForFile(Utils::FileName fileName, bool checkForSettings)
+{
+ QDir overrideDir;
+ if (!checkForSettings || useProjectOverriddenSettings()) {
+ overrideDir = projectPath().toString();
+ if (!overrideDir.isEmpty() && overrideDir.exists(Constants::SETTINGS_FILE_NAME))
+ return overrideDir.filePath(Constants::SETTINGS_FILE_NAME);
}
- if (projectDir.exists(Constants::SETTINGS_FILE_NAME))
- return projectDir.filePath(Constants::SETTINGS_FILE_NAME);
- return projectDir.filePath(Constants::SETTINGS_FILE_ALT_NAME);
+ if (!checkForSettings || useGlobalOverriddenSettings()) {
+ overrideDir = globalPath().toString();
+ if (!overrideDir.isEmpty() && overrideDir.exists(Constants::SETTINGS_FILE_NAME))
+ return overrideDir.filePath(Constants::SETTINGS_FILE_NAME);
+ }
+
+ QDir parentDir(fileName.parentDir().toString());
+ while (!parentDir.exists(Constants::SETTINGS_FILE_NAME)
+ && !parentDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) {
+ if (!parentDir.cdUp())
+ return QString();
+ }
+
+ if (parentDir.exists(Constants::SETTINGS_FILE_NAME))
+ return parentDir.filePath(Constants::SETTINGS_FILE_NAME);
+ return parentDir.filePath(Constants::SETTINGS_FILE_ALT_NAME);
}
static clang::format::FormatStyle constructStyle(bool isGlobal,
@@ -169,6 +200,7 @@ void createStyleFileIfNeeded(bool isGlobal)
if (QFile::exists(configFile))
return;
+ QDir().mkpath(path.parentDir().toString());
std::fstream newStyleFile(configFile.toStdString(), std::fstream::out);
if (newStyleFile.is_open()) {
newStyleFile << clang::format::configurationAsText(constructStyle(isGlobal));
@@ -198,16 +230,11 @@ static QByteArray configBaseStyleName(const QString &configFile)
.trimmed();
}
-clang::format::FormatStyle styleForFile(Utils::FileName fileName)
+static clang::format::FormatStyle styleForFile(Utils::FileName fileName, bool checkForSettings)
{
- bool isGlobal = false;
- QString configFile = configForFile(fileName);
- if (configFile.isEmpty()) {
- Utils::FileName path = fileName = globalPath();
- fileName.appendPath(Constants::SAMPLE_FILE_NAME);
- createStyleFileIfNeeded(true);
- configFile = path.appendPath(Constants::SETTINGS_FILE_NAME).toString();
- }
+ QString configFile = configForFile(fileName, checkForSettings);
+ if (configFile.isEmpty())
+ return constructStyle(true);
Expected style = format::getStyle("file",
fileName.toString().toStdString(),
@@ -219,17 +246,22 @@ clang::format::FormatStyle styleForFile(Utils::FileName fileName)
// do nothing
});
- return constructStyle(isGlobal, configBaseStyleName(configFile));
+ return constructStyle(true, configBaseStyleName(configFile));
+}
+
+clang::format::FormatStyle styleForFile(Utils::FileName fileName)
+{
+ return styleForFile(fileName, true);
}
clang::format::FormatStyle currentProjectStyle()
{
- return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME));
+ return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME), false);
}
clang::format::FormatStyle currentGlobalStyle()
{
- return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME));
+ return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME), false);
}
}
diff --git a/src/plugins/clangformat/clangformatutils.h b/src/plugins/clangformat/clangformatutils.h
index 41e2b5611fa..2c818ffe6aa 100644
--- a/src/plugins/clangformat/clangformatutils.h
+++ b/src/plugins/clangformat/clangformatutils.h
@@ -25,6 +25,7 @@
#pragma once
+#include
#include
#include
@@ -37,6 +38,8 @@ namespace ClangFormat {
// Creates the style for the current project or the global style if needed.
void createStyleFileIfNeeded(bool isGlobal);
+QString currentProjectUniqueId();
+
clang::format::FormatStyle currentProjectStyle();
clang::format::FormatStyle currentGlobalStyle();