File indexing completed on 2024-04-28 04:37:26

0001 /*
0002     SPDX-FileCopyrightText: 2009 Andreas Pakulat <apaku@gmx.de>
0003     SPDX-FileCopyrightText: 2008 Cédric Pasteur <cedric.pasteur@free.fr>
0004     SPDX-FileCopyrightText: 2021 Igor Kushnir <igorkuo@gmail.com>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KDEVPLATFORM_SOURCEFORMATTERCONTROLLER_H
0010 #define KDEVPLATFORM_SOURCEFORMATTERCONTROLLER_H
0011 
0012 #include <interfaces/isourceformattercontroller.h>
0013 #include <interfaces/isourceformatter.h>
0014 
0015 #include <QUrl>
0016 #include <QVector>
0017 #include <QMimeType>
0018 
0019 #include <KXMLGUIClient>
0020 #include <KConfigGroup>
0021 
0022 #include "shellexport.h"
0023 
0024 #include <functional>
0025 #include <map>
0026 
0027 namespace KTextEditor {
0028 class Document;
0029 }
0030 
0031 namespace KDevelop
0032 {
0033 
0034 class Context;
0035 
0036 class ContextMenuExtension;
0037 
0038 class IDocument;
0039 class IProject;
0040 class TextDocument;
0041 class ISourceFormatter;
0042 class IPlugin;
0043 class SourceFormatterControllerPrivate;
0044 
0045 /** \short A singleton class managing all source formatter plugins
0046 */
0047 class KDEVPLATFORMSHELL_EXPORT SourceFormatterController : public ISourceFormatterController, public KXMLGUIClient
0048 {
0049     Q_OBJECT
0050 
0051     friend class SourceFormatterJob;
0052 
0053 public:
0054     static QString kateModeLineConfigKey();
0055     static QString kateOverrideIndentationConfigKey();
0056     static QString styleCaptionKey();
0057     static QString styleShowPreviewKey();
0058     static QString styleContentKey();
0059     static QString styleMimeTypesKey();
0060     static QString styleSampleKey();
0061 
0062     explicit SourceFormatterController(QObject *parent = nullptr);
0063     ~SourceFormatterController() override;
0064     void initialize();
0065     void cleanup();
0066     //----------------- Public API defined in interfaces -------------------
0067     FileFormatterPtr fileFormatter(const QUrl& url) const override;
0068     bool hasFormatters() const override;
0069 
0070     /// style name -> style; heterogeneous lookup is enabled
0071     using StyleMap = std::map<QString, SourceFormatterStyle, std::less<>>;
0072 
0073     /**
0074      * @return all styles that belong to @p formatter
0075      */
0076     StyleMap stylesForFormatter(const KDevelop::ISourceFormatter& formatter) const;
0077 
0078     KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context, QWidget* parent);
0079 
0080     KConfigGroup sessionConfig() const;
0081     KConfigGroup globalConfig() const;
0082 
0083     void settingsChanged();
0084 
0085     void disableSourceFormatting() override;
0086     bool sourceFormattingEnabled() override;
0087 
0088     QVector<KDevelop::ISourceFormatter*> formatters() const;
0089 
0090 Q_SIGNALS:
0091     void formatterLoaded(KDevelop::ISourceFormatter* ifmt);
0092     void formatterUnloading(KDevelop::ISourceFormatter* ifmt);
0093 
0094 private Q_SLOTS:
0095     void updateFormatTextAction();
0096     void beautifySource();
0097     void beautifyLine();
0098     void formatFiles();
0099     void documentLoaded(const QPointer<KDevelop::TextDocument>& doc);
0100     void pluginLoaded(KDevelop::IPlugin* plugin);
0101     void unloadingPlugin(KDevelop::IPlugin* plugin);
0102 
0103 private:
0104     class FileFormatter final : public IFileFormatter
0105     {
0106     public:
0107         /**
0108          * @param url URL of the file to be formatted
0109          */
0110         explicit FileFormatter(QUrl url);
0111 
0112         /**
0113          * Read and store in this object user-configured formatter and style for our file.
0114          * @param formatters loaded and available formatters
0115          * @return @e true on success, otherwise @e false
0116          * @note This function is the second and last initialization step after the constructor.
0117          *       Call it once. Do not call any other non-static member function (other than the
0118          *       destructor) before this function is called and succeeds.
0119          */
0120         bool readFormatterAndStyle(const QVector<ISourceFormatter*>& formatters);
0121 
0122         QString formatterCaption() const;
0123         QString styleCaption() const;
0124 
0125         QString format(const QString& text, const QString& leftContext = QString(),
0126                        const QString& rightContext = QString()) const override;
0127 
0128         /**
0129          * @return @p input with a modeline string corresponding to source formatter configuration for our file
0130          * @note A modeline within @p input is adjusted or a new one is appended to @p input.
0131          */
0132         QString addModeline(QString input) const;
0133 
0134         /**
0135          * Format the open document.
0136          * @param doc our file's document
0137          */
0138         void formatDocument(IDocument& doc) const;
0139 
0140         /**
0141          * Adapt the mode of the editor regarding indentation style.
0142          */
0143         void adaptEditorIndentationMode(KTextEditor::Document* doc, bool ignoreModeline = false) const;
0144 
0145         /**
0146          * Adapt global formatting state to a newly opened project @p project.
0147          */
0148         static void projectOpened(const IProject& project, const QVector<ISourceFormatter*>& formatters);
0149 
0150     private:
0151         explicit FileFormatter(QUrl&& url, QMimeType&& mimeType, const KConfigGroup& sourceFormatterConfig,
0152                                const ISourceFormatter* formatter, SourceFormatterStyle&& style);
0153 
0154         QUrl m_url;
0155         const QMimeType m_mimeType; ///< the MIME type of @a m_url
0156         KConfigGroup m_sourceFormatterConfig; ///< is determined by @a m_url
0157         /**
0158          * The names of @a m_formatter and @a m_style are read from the entry of @a m_sourceFormatterConfig
0159          * at key=@a m_mimeType.name(). @a m_formatter and @a m_style themselves are then formed based on
0160          * @e SourceFormatterController's loaded formatters and on global style configuration.
0161          */
0162         const ISourceFormatter* m_formatter = nullptr;
0163         SourceFormatterStyle m_style;
0164     };
0165 
0166     void resetUi();
0167 
0168 private:
0169     const QScopedPointer<class SourceFormatterControllerPrivate> d_ptr;
0170     Q_DECLARE_PRIVATE(SourceFormatterController)
0171 };
0172 
0173 }
0174 
0175 #endif // KDEVPLATFORM_SOURCEFORMATTERCONTROLLER_H