diff --git a/src/plugins/clangformat/clangformatfile.cpp b/src/plugins/clangformat/clangformatfile.cpp index b984c786627..66bf96fa075 100644 --- a/src/plugins/clangformat/clangformatfile.cpp +++ b/src/plugins/clangformat/clangformatfile.cpp @@ -16,14 +16,32 @@ using namespace ClangFormat; -ClangFormatFile::ClangFormatFile(const TextEditor::ICodeStylePreferences *preferences) +ClangFormatFile::ClangFormatFile( + const TextEditor::ICodeStylePreferences *preferences, const Utils::FilePath &fromFilePath) : m_filePath(filePathToCurrentSettings(preferences)) { if (m_filePath.exists()) return; - // create file and folder + // create folder m_filePath.parentDir().createDir(); + + if (fromFilePath.exists() && fromFilePath.copyFile(m_filePath)) { + auto fileContent = m_filePath.fileContents(); + if (fileContent && !fileContent->contains("yaml-language-server")) { + fileContent->insert( + 0, + "# yaml-language-server: " + "$schema=https://json.schemastore.org/clang-format.json\n"); + m_filePath.writeFileContents(fileContent.value()); + } + parseConfigurationFile(m_filePath, m_style); + return; + } + + // It is done separately from folder because filePath.copyFile doesn't copy if file exists + // ToDo: when behavior of copyFile is changed, combine that block with folder creation block + // create file std::fstream newStyleFile(m_filePath.path().toStdString(), std::fstream::out); if (newStyleFile.is_open()) newStyleFile.close(); diff --git a/src/plugins/clangformat/clangformatfile.h b/src/plugins/clangformat/clangformatfile.h index 6725e266b2d..3c7ab86b3f5 100644 --- a/src/plugins/clangformat/clangformatfile.h +++ b/src/plugins/clangformat/clangformatfile.h @@ -19,7 +19,8 @@ namespace ClangFormat { class ClangFormatFile { public: - explicit ClangFormatFile(const TextEditor::ICodeStylePreferences *preferences); + explicit ClangFormatFile( + const TextEditor::ICodeStylePreferences *preferences, const Utils::FilePath &filePath = {}); clang::format::FormatStyle style(); Utils::FilePath filePath(); diff --git a/src/plugins/clangformat/clangformatglobalconfigwidget.cpp b/src/plugins/clangformat/clangformatglobalconfigwidget.cpp index 052ed865151..c150b909953 100644 --- a/src/plugins/clangformat/clangformatglobalconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatglobalconfigwidget.cpp @@ -5,6 +5,7 @@ #include "clangformatconfigwidget.h" #include "clangformatconstants.h" +#include "clangformatfile.h" #include "clangformatindenter.h" #include "clangformatsettings.h" #include "clangformattr.h" @@ -17,6 +18,8 @@ #include #include +#include +#include #include #include @@ -27,7 +30,9 @@ #include #include #include +#include #include +#include #include using namespace CppEditor; @@ -350,6 +355,59 @@ void ClangFormatGlobalConfigWidget::finish() !ClangFormatSettings::instance().useCustomSettings()); } +class ClangFormatSelectorWidget final : public CodeStyleSelectorWidget +{ +public: + ClangFormatSelectorWidget( + ICodeStylePreferencesFactory *factory, + ProjectExplorer::Project *project = nullptr, + QWidget *parent = nullptr) + : CodeStyleSelectorWidget(factory, project, parent) + {} + +private: + void slotImportClicked() final + { + const FilePath filePath = + FileUtils::getOpenFilePath(this, Tr::tr("Import Code Format"), {}, + Tr::tr("Clang Format (*clang-format*);;All files (*)")); + if (!filePath.isEmpty()) { + QString name = QInputDialog::getText( + this, + Tr::tr("Import Code Style"), + Tr::tr("Enter a name for the imported code style:")); + if (name.isEmpty()) + return; + + CodeStylePool *codeStylePool = m_codeStyle->delegatingPool(); + ICodeStylePreferences *importedStyle = codeStylePool->createCodeStyle(name); + ClangFormatFile file(importedStyle, filePath); + + if (importedStyle) + m_codeStyle->setCurrentDelegate(importedStyle); + else + QMessageBox::warning(this, + Tr::tr("Import Code Style"), + Tr::tr("Cannot import code style from \"%1\".") + .arg(filePath.toUserOutput())); + } + } + + void slotExportClicked() final + { + ICodeStylePreferences *currentPreferences = m_codeStyle->currentPreferences(); + const FilePath filePath = FileUtils::getSaveFilePath( + this, + Tr::tr("Export Code Format"), + FileUtils::homePath(), + Tr::tr("Clang Format (*clang-format*);;All files (*)")); + if (!filePath.isEmpty()) { + FilePath clangFormatFile = filePathToCurrentSettings(currentPreferences); + clangFormatFile.copyFile(filePath); + } + } +}; + class ClangFormatStyleFactory final : public CppCodeStylePreferencesFactory { public: @@ -369,6 +427,12 @@ public: { return new ClangFormatGlobalConfigWidget(codeStyle, project, parent); } + + CodeStyleSelectorWidget *createSelectorWidget( + ProjectExplorer::Project *project, QWidget *parent) final + { + return new ClangFormatSelectorWidget(this, project, parent); + } }; void setupClangFormatStyleFactory(QObject *guard) diff --git a/src/plugins/texteditor/codestyleeditor.cpp b/src/plugins/texteditor/codestyleeditor.cpp index 070a230e384..98e36bf5984 100644 --- a/src/plugins/texteditor/codestyleeditor.cpp +++ b/src/plugins/texteditor/codestyleeditor.cpp @@ -30,7 +30,7 @@ CodeStyleEditor::CodeStyleEditor(ICodeStylePreferencesFactory *factory, { m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); - auto selector = new CodeStyleSelectorWidget(factory, project, this); + auto selector = m_factory->createSelectorWidget(project, this); selector->setCodeStyle(codeStyle); m_additionalGlobalSettingsWidget = factory->createAdditionalGlobalSettings(codeStyle, project, diff --git a/src/plugins/texteditor/codestylepool.cpp b/src/plugins/texteditor/codestylepool.cpp index 949b38ab336..d593bae2e01 100644 --- a/src/plugins/texteditor/codestylepool.cpp +++ b/src/plugins/texteditor/codestylepool.cpp @@ -135,6 +135,20 @@ ICodeStylePreferences *CodeStylePool::createCodeStyle(const QByteArray &id, cons return codeStyle; } +ICodeStylePreferences *CodeStylePool::createCodeStyle(const QString &displayName) +{ + if (!d->m_factory) + return nullptr; + + ICodeStylePreferences *codeStyle = d->m_factory->createCodeStyle(); + codeStyle->setDisplayName(displayName); + + addCodeStyle(codeStyle); + saveCodeStyle(codeStyle); + + return codeStyle; +} + void CodeStylePool::addCodeStyle(ICodeStylePreferences *codeStyle) { const QByteArray newId = d->generateUniqueId(codeStyle->id()); diff --git a/src/plugins/texteditor/codestylepool.h b/src/plugins/texteditor/codestylepool.h index 3119d1a27b4..1ebbbacc5df 100644 --- a/src/plugins/texteditor/codestylepool.h +++ b/src/plugins/texteditor/codestylepool.h @@ -30,6 +30,7 @@ public: ICodeStylePreferences *cloneCodeStyle(ICodeStylePreferences *originalCodeStyle); ICodeStylePreferences *createCodeStyle(const QByteArray &id, const TabSettings &tabSettings, const QVariant &codeStyleData, const QString &displayName); + ICodeStylePreferences *createCodeStyle(const QString &displayName); // ownership is passed to the pool void addCodeStyle(ICodeStylePreferences *codeStyle); // is removed and deleted diff --git a/src/plugins/texteditor/codestyleselectorwidget.h b/src/plugins/texteditor/codestyleselectorwidget.h index e1bdf588da2..fe4299a5fac 100644 --- a/src/plugins/texteditor/codestyleselectorwidget.h +++ b/src/plugins/texteditor/codestyleselectorwidget.h @@ -32,20 +32,22 @@ public: void setCodeStyle(ICodeStylePreferences *codeStyle); +protected: + ICodeStylePreferences *m_codeStyle = nullptr; + private: void slotComboBoxActivated(int index); void slotCurrentDelegateChanged(ICodeStylePreferences *delegate); void slotCopyClicked(); void slotRemoveClicked(); - void slotImportClicked(); - void slotExportClicked(); + virtual void slotImportClicked(); + virtual void slotExportClicked(); void slotCodeStyleAdded(ICodeStylePreferences *codeStylePreferences); void slotCodeStyleRemoved(ICodeStylePreferences *codeStylePreferences); void slotUpdateName(ICodeStylePreferences *codeStylePreferences); void updateName(ICodeStylePreferences *codeStyle); ICodeStylePreferencesFactory *m_factory; - ICodeStylePreferences *m_codeStyle = nullptr; ProjectExplorer::Project *m_project = nullptr; QString displayName(ICodeStylePreferences *codeStyle) const; diff --git a/src/plugins/texteditor/icodestylepreferencesfactory.cpp b/src/plugins/texteditor/icodestylepreferencesfactory.cpp index 19f35338071..3551e0e20e2 100644 --- a/src/plugins/texteditor/icodestylepreferencesfactory.cpp +++ b/src/plugins/texteditor/icodestylepreferencesfactory.cpp @@ -4,6 +4,7 @@ #include "icodestylepreferencesfactory.h" #include "codestyleeditor.h" +#include "codestyleselectorwidget.h" using namespace TextEditor; @@ -22,3 +23,9 @@ CodeStyleEditorWidget *ICodeStylePreferencesFactory::createAdditionalGlobalSetti { return nullptr; } + +CodeStyleSelectorWidget *ICodeStylePreferencesFactory::createSelectorWidget( + ProjectExplorer::Project *project, QWidget *parent) +{ + return new CodeStyleSelectorWidget(this, project, parent); +} diff --git a/src/plugins/texteditor/icodestylepreferencesfactory.h b/src/plugins/texteditor/icodestylepreferencesfactory.h index 6a4c7f2f54f..0e8df88d353 100644 --- a/src/plugins/texteditor/icodestylepreferencesfactory.h +++ b/src/plugins/texteditor/icodestylepreferencesfactory.h @@ -16,6 +16,7 @@ namespace ProjectExplorer { class Project; } namespace TextEditor { class ICodeStylePreferences; +class CodeStyleSelectorWidget; class TEXTEDITOR_EXPORT CodeStyleEditorWidget : public QWidget { @@ -50,6 +51,8 @@ public: virtual CodeStyleEditorWidget *createEditor(ICodeStylePreferences *preferences, ProjectExplorer::Project *project = nullptr, QWidget *parent = nullptr) const = 0; + virtual CodeStyleSelectorWidget *createSelectorWidget( + ProjectExplorer::Project *project, QWidget *parent = nullptr); virtual TextEditor::Indenter *createIndenter(QTextDocument *doc) const = 0; virtual QString snippetProviderGroupId() const = 0; virtual QString previewText() const = 0;