diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 0dc6d4c54fe..1a28f4d6995 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -115,7 +116,7 @@ void ClangFormatConfigWidget::showEvent(QShowEvent *event) } ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *project, QWidget *parent) - : CodeStyleEditorWidget(parent) + : CppCodeStyleWidget(parent) , m_project(project) , m_checks(std::make_unique()) , m_ui(std::make_unique()) @@ -438,6 +439,29 @@ void ClangFormatConfigWidget::saveChanges(QObject *sender) fillTable(); updatePreview(); + synchronize(); +} + +void ClangFormatConfigWidget::setCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings) +{ + m_config->fromCppCodeStyleSettings(settings); + + fillTable(); + updatePreview(); +} + +void ClangFormatConfigWidget::setTabSettings(const TextEditor::TabSettings &settings) +{ + m_config->fromTabSettings(settings); + + fillTable(); + updatePreview(); +} + +void ClangFormatConfigWidget::synchronize() +{ + emit codeStyleSettingsChanged(m_config->toCppCodeStyleSettings(m_project)); + emit tabSettingsChanged(m_config->toTabSettings(m_project)); } void ClangFormatConfigWidget::apply() diff --git a/src/plugins/clangformat/clangformatconfigwidget.h b/src/plugins/clangformat/clangformatconfigwidget.h index 4c261f99924..cf4bc1104c3 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.h +++ b/src/plugins/clangformat/clangformatconfigwidget.h @@ -25,18 +25,15 @@ #pragma once -#include +#include #include #include -namespace ProjectExplorer { -class Project; -} -namespace TextEditor { -class SnippetEditorWidget; -} +namespace ProjectExplorer { class Project; } +namespace TextEditor { class SnippetEditorWidget; } +namespace CppEditor { class CppCodeStyleSettings; } namespace ClangFormat { @@ -46,7 +43,7 @@ class ClangFormatChecksWidget; } class ClangFormatFile; -class ClangFormatConfigWidget : public TextEditor::CodeStyleEditorWidget +class ClangFormatConfigWidget : public CppEditor::CppCodeStyleWidget { Q_OBJECT @@ -55,6 +52,9 @@ public: QWidget *parent = nullptr); ~ClangFormatConfigWidget() override; void apply() override; + void setCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings) override; + void setTabSettings(const TextEditor::TabSettings &settings) override; + void synchronize() override; private: void onTableChanged(); diff --git a/src/plugins/clangformat/clangformatfile.cpp b/src/plugins/clangformat/clangformatfile.cpp index c9955ef2a3e..44adde76b04 100644 --- a/src/plugins/clangformat/clangformatfile.cpp +++ b/src/plugins/clangformat/clangformatfile.cpp @@ -24,6 +24,12 @@ ****************************************************************************/ #include "clangformatfile.h" +#include "clangformatsettings.h" +#include +#include +#include +#include + #include using namespace ClangFormat; @@ -105,7 +111,7 @@ void ClangFormatFile::saveNewFormat() // workaround: configurationAsText() add comment "# " before BasedOnStyle line const int pos = style.find("# BasedOnStyle"); - if (pos < int(style.size())) + if (pos != int(std::string::npos)) style.erase(pos, 2); m_filePath.writeFileContents(QByteArray::fromStdString(style)); } @@ -114,3 +120,138 @@ void ClangFormatFile::saveNewFormat(QByteArray style) { m_filePath.writeFileContents(style); } + +CppEditor::CppCodeStyleSettings ClangFormatFile::toCppCodeStyleSettings( + ProjectExplorer::Project *project) const +{ + using namespace clang::format; + auto settings = CppEditor::CppCodeStyleSettings::getProjectCodeStyle(project); + + FormatStyle style; + style.Language = clang::format::FormatStyle::LK_Cpp; + const std::error_code error = parseConfiguration(m_filePath.fileContents().toStdString(), + &style); + QTC_ASSERT(error.value() == static_cast(ParseError::Success), return settings); + + // Modifier offset should be opposite to indent width in order indentAccessSpecifiers + // to be false + settings.indentAccessSpecifiers = (style.AccessModifierOffset != -1 * style.IndentWidth); + + settings.indentNamespaceBody = style.NamespaceIndentation + == FormatStyle::NamespaceIndentationKind::NI_All; + settings.indentNamespaceBraces = settings.indentNamespaceBody; + + settings.indentClassBraces = style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths; + settings.indentEnumBraces = settings.indentClassBraces; + settings.indentBlockBraces = settings.indentClassBraces; + settings.indentFunctionBraces = settings.indentClassBraces; + + settings.indentSwitchLabels = style.IndentCaseLabels; + settings.indentBlocksRelativeToSwitchLabels = style.IndentCaseBlocks; + settings.indentStatementsRelativeToSwitchLabels = style.IndentCaseBlocks; + settings.indentControlFlowRelativeToSwitchLabels = style.IndentCaseBlocks; + + if (style.DerivePointerAlignment + && ClangFormatSettings::instance().formatCodeInsteadOfIndent()) { + settings.bindStarToIdentifier = style.PointerAlignment == FormatStyle::PAS_Right; + settings.bindStarToTypeName = style.PointerAlignment == FormatStyle::PAS_Left; + settings.bindStarToLeftSpecifier = style.PointerAlignment == FormatStyle::PAS_Left; + settings.bindStarToRightSpecifier = style.PointerAlignment == FormatStyle::PAS_Right; + } + + return settings; +} + +void ClangFormatFile::fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings) +{ + using namespace clang::format; + if (settings.indentAccessSpecifiers) + m_style.AccessModifierOffset = 0; + else + m_style.AccessModifierOffset = -1 * m_style.IndentWidth; + + if (settings.indentNamespaceBody || settings.indentNamespaceBraces) + m_style.NamespaceIndentation = FormatStyle::NamespaceIndentationKind::NI_All; + + if (settings.indentClassBraces || settings.indentEnumBraces || settings.indentBlockBraces + || settings.indentFunctionBraces) + m_style.BreakBeforeBraces = FormatStyle::BS_Whitesmiths; + + m_style.IndentCaseLabels = settings.indentSwitchLabels; + m_style.IndentCaseBlocks = settings.indentBlocksRelativeToSwitchLabels + || settings.indentStatementsRelativeToSwitchLabels + || settings.indentControlFlowRelativeToSwitchLabels; + + if (settings.alignAssignments) + m_style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; + + if (settings.extraPaddingForConditionsIfConfusingAlign) + m_style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; + + m_style.DerivePointerAlignment = settings.bindStarToIdentifier || settings.bindStarToTypeName + || settings.bindStarToLeftSpecifier + || settings.bindStarToRightSpecifier; + + if ((settings.bindStarToIdentifier || settings.bindStarToRightSpecifier) + && ClangFormatSettings::instance().formatCodeInsteadOfIndent()) + m_style.PointerAlignment = FormatStyle::PAS_Right; + + if ((settings.bindStarToTypeName || settings.bindStarToLeftSpecifier) + && ClangFormatSettings::instance().formatCodeInsteadOfIndent()) + m_style.PointerAlignment = FormatStyle::PAS_Left; + + saveNewFormat(); +} + +TextEditor::TabSettings ClangFormatFile::toTabSettings(ProjectExplorer::Project *project) const +{ + using namespace clang::format; + auto settings = CppEditor::CppCodeStyleSettings::getProjectTabSettings(project); + + FormatStyle style; + style.Language = clang::format::FormatStyle::LK_Cpp; + const std::error_code error = parseConfiguration(m_filePath.fileContents().toStdString(), + &style); + QTC_ASSERT(error.value() == static_cast(ParseError::Success), return settings); + + settings.m_indentSize = style.IndentWidth; + settings.m_tabSize = style.TabWidth; + + switch (style.UseTab) { + case FormatStyle::UT_AlignWithSpaces: + case FormatStyle::UT_ForIndentation: + case FormatStyle::UT_ForContinuationAndIndentation: + settings.m_tabPolicy = TextEditor::TabSettings::TabPolicy::MixedTabPolicy; + break; + case FormatStyle::UT_Never: + settings.m_tabPolicy = TextEditor::TabSettings::TabPolicy::SpacesOnlyTabPolicy; + break; + case FormatStyle::UT_Always: + settings.m_tabPolicy = TextEditor::TabSettings::TabPolicy::TabsOnlyTabPolicy; + break; + } + + return settings; +} + +void ClangFormatFile::fromTabSettings(const TextEditor::TabSettings &settings) +{ + using namespace clang::format; + + m_style.IndentWidth = settings.m_indentSize; + m_style.TabWidth = settings.m_tabSize; + + switch (settings.m_tabPolicy) { + case TextEditor::TabSettings::TabPolicy::MixedTabPolicy: + m_style.UseTab = FormatStyle::UT_ForContinuationAndIndentation; + break; + case TextEditor::TabSettings::TabPolicy::SpacesOnlyTabPolicy: + m_style.UseTab = FormatStyle::UT_Never; + break; + case TextEditor::TabSettings::TabPolicy::TabsOnlyTabPolicy: + m_style.UseTab = FormatStyle::UT_Always; + break; + } + + saveNewFormat(); +} diff --git a/src/plugins/clangformat/clangformatfile.h b/src/plugins/clangformat/clangformatfile.h index 3fe9010f44e..f0dddd4ec03 100644 --- a/src/plugins/clangformat/clangformatfile.h +++ b/src/plugins/clangformat/clangformatfile.h @@ -28,6 +28,10 @@ #include "utils/filepath.h" #include +namespace CppEditor { class CppCodeStyleSettings; } +namespace ProjectExplorer { class Project; } +namespace TextEditor { class TabSettings; } + namespace ClangFormat { class ClangFormatFile @@ -46,6 +50,10 @@ public: using Field = std::pair; QString changeFields(QList fields); QString changeField(Field field); + CppEditor::CppCodeStyleSettings toCppCodeStyleSettings(ProjectExplorer::Project *project) const; + TextEditor::TabSettings toTabSettings(ProjectExplorer::Project *project) const; + void fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings); + void fromTabSettings(const TextEditor::TabSettings &settings); private: void saveNewFormat(); @@ -56,5 +64,4 @@ private: clang::format::FormatStyle m_style; }; - } // namespace ClangFormat diff --git a/src/plugins/clangformat/clangformatplugin.cpp b/src/plugins/clangformat/clangformatplugin.cpp index 993f7c83ef6..87322175726 100644 --- a/src/plugins/clangformat/clangformatplugin.cpp +++ b/src/plugins/clangformat/clangformatplugin.cpp @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -82,7 +83,7 @@ public: return new ClangFormatIndenter(doc); } - std::pair additionalTab(QWidget *parent) const override + std::pair additionalTab(QWidget *parent) const override { if (!parent) return {new ClangFormatConfigWidget(), tr("ClangFormat")}; diff --git a/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp b/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp index 7228e2be8e9..33fa8d6103a 100644 --- a/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp +++ b/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp @@ -105,13 +105,12 @@ QWidget *CppCodeStylePreferencesFactory::createEditor(TextEditor::ICodeStylePref return nullptr; auto widget = new Internal::CppCodeStylePreferencesWidget(parent); - const auto tab = additionalTab(parent); - if (tab.first) { - widget->addTab(tab.first, tab.second); - } - widget->layout()->setContentsMargins(0, 0, 0, 0); widget->setCodeStyle(cppPreferences); + + const auto tab = additionalTab(parent); + widget->addTab(tab.first, tab.second); + return widget; } @@ -130,7 +129,7 @@ QString CppCodeStylePreferencesFactory::previewText() const return QLatin1String(defaultPreviewText); } -std::pair CppCodeStylePreferencesFactory::additionalTab(QWidget *parent) const +std::pair CppCodeStylePreferencesFactory::additionalTab(QWidget *parent) const { Q_UNUSED(parent) return {nullptr, ""}; diff --git a/src/plugins/cppeditor/cppcodestylepreferencesfactory.h b/src/plugins/cppeditor/cppcodestylepreferencesfactory.h index f7ca14c4a7a..ce38ae6fb79 100644 --- a/src/plugins/cppeditor/cppcodestylepreferencesfactory.h +++ b/src/plugins/cppeditor/cppcodestylepreferencesfactory.h @@ -30,6 +30,7 @@ #include namespace CppEditor { +class CppCodeStyleWidget; class CPPEDITOR_EXPORT CppCodeStylePreferencesFactory : public TextEditor::ICodeStylePreferencesFactory { @@ -44,7 +45,7 @@ public: TextEditor::Indenter *createIndenter(QTextDocument *doc) const override; QString snippetProviderGroupId() const override; QString previewText() const override; - virtual std::pair additionalTab(QWidget *parent) const; + virtual std::pair additionalTab(QWidget *parent) const; }; } // namespace CppEditor diff --git a/src/plugins/cppeditor/cppcodestylesettings.cpp b/src/plugins/cppeditor/cppcodestylesettings.cpp index 1c81cc610c5..d4b2f3f4d31 100644 --- a/src/plugins/cppeditor/cppcodestylesettings.cpp +++ b/src/plugins/cppeditor/cppcodestylesettings.cpp @@ -177,27 +177,31 @@ bool CppCodeStyleSettings::equals(const CppCodeStyleSettings &rhs) const ; } -Utils::optional CppCodeStyleSettings::currentProjectCodeStyle() +CppCodeStyleSettings CppCodeStyleSettings::getProjectCodeStyle(ProjectExplorer::Project *project) { - ProjectExplorer::Project *project = ProjectExplorer::ProjectTree::currentProject(); if (!project) - return {}; + return currentGlobalCodeStyle(); ProjectExplorer::EditorConfiguration *editorConfiguration = project->editorConfiguration(); - QTC_ASSERT(editorConfiguration, return {}); + QTC_ASSERT(editorConfiguration, return currentGlobalCodeStyle()); TextEditor::ICodeStylePreferences *codeStylePreferences = editorConfiguration->codeStyle(Constants::CPP_SETTINGS_ID); - QTC_ASSERT(codeStylePreferences, return {}); + QTC_ASSERT(codeStylePreferences, return currentGlobalCodeStyle()); auto cppCodeStylePreferences = - dynamic_cast(codeStylePreferences); + dynamic_cast(codeStylePreferences); if (!cppCodeStylePreferences) - return {}; + return currentGlobalCodeStyle(); return cppCodeStylePreferences->currentCodeStyleSettings(); } +CppCodeStyleSettings CppCodeStyleSettings::currentProjectCodeStyle() +{ + return getProjectCodeStyle(ProjectExplorer::ProjectTree::currentProject()); +} + CppCodeStyleSettings CppCodeStyleSettings::currentGlobalCodeStyle() { CppCodeStylePreferences *cppCodeStylePreferences = CppToolsSettings::instance()->cppCodeStyle(); @@ -206,9 +210,8 @@ CppCodeStyleSettings CppCodeStyleSettings::currentGlobalCodeStyle() return cppCodeStylePreferences->currentCodeStyleSettings(); } -TextEditor::TabSettings CppCodeStyleSettings::currentProjectTabSettings() +TextEditor::TabSettings CppCodeStyleSettings::getProjectTabSettings(ProjectExplorer::Project *project) { - ProjectExplorer::Project *project = ProjectExplorer::ProjectTree::currentProject(); if (!project) return currentGlobalTabSettings(); @@ -221,6 +224,11 @@ TextEditor::TabSettings CppCodeStyleSettings::currentProjectTabSettings() return codeStylePreferences->currentTabSettings(); } +TextEditor::TabSettings CppCodeStyleSettings::currentProjectTabSettings() +{ + return getProjectTabSettings(ProjectExplorer::ProjectTree::currentProject()); +} + TextEditor::TabSettings CppCodeStyleSettings::currentGlobalTabSettings() { CppCodeStylePreferences *cppCodeStylePreferences diff --git a/src/plugins/cppeditor/cppcodestylesettings.h b/src/plugins/cppeditor/cppcodestylesettings.h index b554338dcb2..3cda6e44c2b 100644 --- a/src/plugins/cppeditor/cppcodestylesettings.h +++ b/src/plugins/cppeditor/cppcodestylesettings.h @@ -37,6 +37,7 @@ QT_END_NAMESPACE namespace CPlusPlus { class Overview; } namespace TextEditor { class TabSettings; } +namespace ProjectExplorer { class Project; } namespace CppEditor { @@ -97,8 +98,10 @@ public: bool operator==(const CppCodeStyleSettings &s) const { return equals(s); } bool operator!=(const CppCodeStyleSettings &s) const { return !equals(s); } - static Utils::optional currentProjectCodeStyle(); + static CppCodeStyleSettings getProjectCodeStyle(ProjectExplorer::Project *project); + static CppCodeStyleSettings currentProjectCodeStyle(); static CppCodeStyleSettings currentGlobalCodeStyle(); + static TextEditor::TabSettings getProjectTabSettings(ProjectExplorer::Project *project); static TextEditor::TabSettings currentProjectTabSettings(); static TextEditor::TabSettings currentGlobalTabSettings(); diff --git a/src/plugins/cppeditor/cppcodestylesettingspage.cpp b/src/plugins/cppeditor/cppcodestylesettingspage.cpp index 3cf8d08d52e..c56f69dc95b 100644 --- a/src/plugins/cppeditor/cppcodestylesettingspage.cpp +++ b/src/plugins/cppeditor/cppcodestylesettingspage.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -222,6 +223,11 @@ void CppCodeStylePreferencesWidget::setTabSettings(const TabSettings &settings) m_ui->tabSettingsWidget->setTabSettings(settings); } +TextEditor::TabSettings CppCodeStylePreferencesWidget::tabSettings() const +{ + return m_ui->tabSettingsWidget->tabSettings(); +} + void CppCodeStylePreferencesWidget::setCodeStyleSettings(const CppCodeStyleSettings &s, bool preview) { const bool wasBlocked = m_blockUpdates; @@ -274,7 +280,7 @@ void CppCodeStylePreferencesWidget::slotCodeStyleSettingsChanged() if (current) current->setCodeStyleSettings(cppCodeStyleSettings()); } - + emit codeStyleSettingsChanged(cppCodeStyleSettings()); updatePreview(); } @@ -289,6 +295,7 @@ void CppCodeStylePreferencesWidget::slotTabSettingsChanged(const TabSettings &se current->setTabSettings(settings); } + emit tabSettingsChanged(settings); updatePreview(); } @@ -337,9 +344,26 @@ void CppCodeStylePreferencesWidget::setVisualizeWhitespace(bool on) } } -void CppCodeStylePreferencesWidget::addTab(QWidget *page, QString tabName) +void CppCodeStylePreferencesWidget::addTab(CppCodeStyleWidget *page, QString tabName) { + QTC_ASSERT(page, return); m_ui->categoryTab->addTab(page, tabName); + + connect(page, &CppEditor::CppCodeStyleWidget::codeStyleSettingsChanged, + this, [this](const CppEditor::CppCodeStyleSettings &settings) { + setCodeStyleSettings(settings, true); + }); + + connect(page, &CppEditor::CppCodeStyleWidget::tabSettingsChanged, + this, &CppCodeStylePreferencesWidget::setTabSettings); + + connect(this, &CppCodeStylePreferencesWidget::codeStyleSettingsChanged, + page, &CppCodeStyleWidget::setCodeStyleSettings); + + connect(this, &CppCodeStylePreferencesWidget::tabSettingsChanged, + page, &CppCodeStyleWidget::setTabSettings); + + page->synchronize(); } // ------------------ CppCodeStyleSettingsPage diff --git a/src/plugins/cppeditor/cppcodestylesettingspage.h b/src/plugins/cppeditor/cppcodestylesettingspage.h index 17940c4c725..7c04185165f 100644 --- a/src/plugins/cppeditor/cppcodestylesettingspage.h +++ b/src/plugins/cppeditor/cppcodestylesettingspage.h @@ -39,11 +39,29 @@ namespace TextEditor { class TabSettings; class SnippetEditorWidget; class CodeStyleEditor; + class CodeStyleEditorWidget; } namespace CppEditor { class CppCodeStylePreferences; +class CPPEDITOR_EXPORT CppCodeStyleWidget : public TextEditor::CodeStyleEditorWidget +{ + Q_OBJECT +public: + CppCodeStyleWidget(QWidget *parent = nullptr) + : CodeStyleEditorWidget(parent) + {} + + virtual void setCodeStyleSettings(const CppEditor::CppCodeStyleSettings &) {} + virtual void setTabSettings(const TextEditor::TabSettings &) {} + virtual void synchronize() {} + +signals: + void codeStyleSettingsChanged(const CppEditor::CppCodeStyleSettings &); + void tabSettingsChanged(const TextEditor::TabSettings &); +}; + namespace Internal { namespace Ui { class CppCodeStyleSettingsPage; } @@ -56,7 +74,7 @@ public: ~CppCodeStylePreferencesWidget() override; void setCodeStyle(CppCodeStylePreferences *codeStylePreferences); - void addTab(QWidget *page, QString tabName); + void addTab(CppCodeStyleWidget *page, QString tabName); private: void decorateEditors(const TextEditor::FontSettings &fontSettings); @@ -65,6 +83,7 @@ private: void slotCodeStyleSettingsChanged(); void updatePreview(); void setTabSettings(const TextEditor::TabSettings &settings); + TextEditor::TabSettings tabSettings() const; void setCodeStyleSettings(const CppCodeStyleSettings &settings, bool preview = true); void slotCurrentPreferencesChanged(TextEditor::ICodeStylePreferences *, bool preview = true); @@ -74,6 +93,9 @@ private: Ui::CppCodeStyleSettingsPage *m_ui; QList m_previews; bool m_blockUpdates = false; +signals: + void codeStyleSettingsChanged(const CppEditor::CppCodeStyleSettings &); + void tabSettingsChanged(const TextEditor::TabSettings &); };