diff --git a/src/plugins/texteditor/CMakeLists.txt b/src/plugins/texteditor/CMakeLists.txt index 2a99947b933..81d562778d5 100644 --- a/src/plugins/texteditor/CMakeLists.txt +++ b/src/plugins/texteditor/CMakeLists.txt @@ -68,6 +68,7 @@ add_qtc_plugin(TextEditor icodestylepreferencesfactory.cpp icodestylepreferencesfactory.h indenter.h ioutlinewidget.h + jsoneditor.cpp jsoneditor.h linenumberfilter.cpp linenumberfilter.h marginsettings.cpp marginsettings.h markdowneditor.cpp markdowneditor.h diff --git a/src/plugins/texteditor/jsoneditor.cpp b/src/plugins/texteditor/jsoneditor.cpp new file mode 100644 index 00000000000..6bdc698ea20 --- /dev/null +++ b/src/plugins/texteditor/jsoneditor.cpp @@ -0,0 +1,95 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "jsoneditor.h" + +#include "autocompleter.h" +#include "textdocument.h" +#include "texteditoractionhandler.h" +#include "texteditortr.h" +#include "textindenter.h" + +namespace TextEditor::Internal { + +const char JSON_EDITOR_ID[] = "Editors.Json"; +const char JSON_MIME_TYPE[] = "application/json"; + +static int startsWith(const QString &line, const QString &closingChars) +{ + int count = 0; + for (const QChar &lineChar : line) { + if (closingChars.contains(lineChar)) + ++count; + else if (!lineChar.isSpace()) + break; + } + return count; +} + +class JsonAutoCompleter : public AutoCompleter +{ + bool contextAllowsElectricCharacters(const QTextCursor &cursor) const override { return true; } +}; + +class JsonIndenter : public TextIndenter +{ +public: + JsonIndenter(QTextDocument *doc) : TextIndenter(doc) {} + + bool isElectricCharacter(const QChar &c) const override + { + static QString echars("{}[]"); + return echars.contains(c); + } + + int indentFor(const QTextBlock &block, + const TabSettings &tabSettings, + int /*cursorPositionInEditor*/) override + { + QTextBlock previous = block.previous(); + if (!previous.isValid()) + return 0; + + QString previousText = previous.text(); + while (previousText.trimmed().isEmpty()) { + previous = previous.previous(); + if (!previous.isValid()) + return 0; + previousText = previous.text(); + } + + int indent = tabSettings.indentationColumn(previousText); + + int adjust = previousText.count('{') + previousText.count('['); + adjust -= previousText.count('}') + previousText.count(']'); + adjust += startsWith(previousText, "}]") - startsWith(block.text(), "}]"); + adjust *= tabSettings.m_indentSize; + + return qMax(0, indent + adjust); + } + + void indentBlock(const QTextBlock &block, + const QChar &typedChar, + const TabSettings &tabSettings, + int cursorPositionInEditor) override + { + tabSettings.indentLine(block, indentFor(block, tabSettings, cursorPositionInEditor)); + } +}; + +JsonEditorFactory::JsonEditorFactory() +{ + setId(JSON_EDITOR_ID); + setDisplayName(Tr::tr("Json Editor")); + addMimeType(JSON_MIME_TYPE); + + setEditorCreator([] { return new BaseTextEditor; }); + setEditorWidgetCreator([] { return new TextEditorWidget; }); + setDocumentCreator([] { return new TextDocument(JSON_EDITOR_ID); }); + setAutoCompleterCreator([] { return new JsonAutoCompleter; }); + setIndenterCreator([](QTextDocument *doc) { return new JsonIndenter(doc); }); + setEditorActionHandlers(TextEditorActionHandler::Format); + setUseGenericHighlighter(true); +} + +} // namespace TextEditor::Internal diff --git a/src/plugins/texteditor/jsoneditor.h b/src/plugins/texteditor/jsoneditor.h new file mode 100644 index 00000000000..d1f783fed70 --- /dev/null +++ b/src/plugins/texteditor/jsoneditor.h @@ -0,0 +1,16 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "texteditor.h" + +namespace TextEditor::Internal { + +class JsonEditorFactory final : public TextEditorFactory +{ +public: + JsonEditorFactory(); +}; + +} // TextEditor::Internal diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index fa8441f29ef..0a424aeaa58 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -90,6 +90,8 @@ Project { "icodestylepreferencesfactory.h", "indenter.h", "ioutlinewidget.h", + "jsoneditor.cpp", + "jsoneditor.h", "linenumberfilter.cpp", "linenumberfilter.h", "marginsettings.cpp", diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp index 70a50856145..67c621bcc36 100644 --- a/src/plugins/texteditor/texteditorplugin.cpp +++ b/src/plugins/texteditor/texteditorplugin.cpp @@ -10,6 +10,7 @@ #include "fontsettings.h" #include "highlighter.h" #include "icodestylepreferences.h" +#include "jsoneditor.h" #include "linenumberfilter.h" #include "markdowneditor.h" #include "outlinefactory.h" @@ -76,6 +77,7 @@ public: PlainTextEditorFactory plainTextEditorFactory; MarkdownEditorFactory markdownEditorFactory; + JsonEditorFactory jsonEditorFactory; }; static TextEditorPlugin *m_instance = nullptr;