File indexing completed on 2024-06-16 04:16:25

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Mathias Wein <lynx.mw+kde@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #ifndef WGCONFIG_H
0008 #define WGCONFIG_H
0009 
0010 #include <KisColorSelectorConfiguration.h>
0011 
0012 #include <ksharedconfig.h>
0013 #include <kconfiggroup.h>
0014 
0015 #include <QVector4D>
0016 
0017 #include <type_traits>
0018 
0019 class KoColorSpace;
0020 
0021 namespace WGConfig {
0022 
0023 template<class T> struct GenericSetting
0024 {
0025     typedef T ValueType;
0026 
0027     T readValue(const KConfigGroup &group) const
0028     {
0029         return group.readEntry(name, defaultValue);
0030     }
0031 
0032     void writeValue(KConfigGroup &group, const T &value) const
0033     {
0034         group.writeEntry(name, value);
0035     }
0036 
0037     QString name;
0038     T defaultValue;
0039 };
0040 
0041 template<class T> struct NumericSetting
0042 {
0043     typedef T ValueType;
0044     // the storage type, for enums it's the underlying integral type, otherwise T
0045     // NOTE: The use of std::remove_cv is because std::type_identity is C++20
0046     using ST = typename std::conditional_t<std::is_enum<T>::value, std::underlying_type<T>, std::remove_cv<T>>::type;
0047 
0048     T readValue(const KConfigGroup &group) const
0049     {
0050         T value = static_cast<T>(group.readEntry(name, static_cast<ST>(defaultValue)));
0051         return applyLimits(value);
0052     }
0053 
0054     void writeValue(KConfigGroup &group, const T &value) const
0055     {
0056         group.writeEntry(name, static_cast<ST>(value));
0057     }
0058 
0059     T boundFunc(const T &min, const T &val, const T &max) const
0060     {
0061         return qBound(min, val, max);
0062     }
0063 
0064     T applyLimits(T value) const {
0065         if (enforceLimits) {
0066             return boundFunc(minValue, value, maxValue);
0067         }
0068         return value;
0069     }
0070     QString name;
0071     T defaultValue;
0072     T minValue;
0073     T maxValue;
0074     bool enforceLimits {false};
0075 };
0076 
0077 template<>
0078 inline QSize NumericSetting<QSize>::boundFunc(const QSize &min, const QSize &val, const QSize &max) const
0079 {
0080     return val.expandedTo(min).boundedTo(max);
0081 }
0082 
0083 struct ShadeLine {
0084     ShadeLine() = default;
0085     explicit ShadeLine(QVector4D grad, QVector4D offs=QVector4D(), int patchC=-1)
0086         : gradient(grad), offset(offs), patchCount(patchC) {}
0087     QVector4D gradient;
0088     QVector4D offset;
0089     int patchCount {-1}; // negative value means slider mode
0090 };
0091 
0092 class WGConfig
0093 {
0094 public:
0095 
0096     explicit WGConfig(bool readOnly = true);
0097     ~WGConfig();
0098 
0099     template<class T>
0100     typename T::ValueType get(const T &setting, bool defaultValue = false) const
0101     {
0102         if (defaultValue) {
0103             return setting.defaultValue;
0104         }
0105         return setting.readValue(m_cfg);
0106     }
0107 
0108     template<class T>
0109     void set(const T &setting, const typename T::ValueType &value) { setting.writeValue(m_cfg, value); }
0110 
0111     static QString configGroupName();
0112 
0113     KisColorSelectorConfiguration colorSelectorConfiguration() const;
0114     void setColorSelectorConfiguration(const KisColorSelectorConfiguration &config);
0115 
0116     QVector<KisColorSelectorConfiguration> favoriteConfigurations(bool defaultValue = false) const;
0117     static QVector<KisColorSelectorConfiguration> defaultFavoriteConfigurations();
0118     void setFavoriteConfigurations(const QVector<KisColorSelectorConfiguration> &favoriteConfigs);
0119 
0120     // shade selector
0121     static QVector<ShadeLine> defaultShadeSelectorLines();
0122     QVector<ShadeLine> shadeSelectorLines(bool defaultValue = false) const;
0123     void setShadeSelectorLines(const QVector<ShadeLine> &shadeLines);
0124 
0125     const KoColorSpace* customSelectionColorSpace(bool defaultValue = false) const;
0126     void setCustomSelectionColorSpace(const KoColorSpace *cs);
0127 
0128     template<class T>
0129     void writeEntry(const QString& name, const T& value) {
0130         m_cfg.writeEntry(name, value);
0131     }
0132 
0133     template<class T>
0134     T readEntry(const QString& name, const T& defaultValue=T()) {
0135         return m_cfg.readEntry(name, defaultValue);
0136     }
0137 
0138 
0139 
0140     static const KisColorSelectorConfiguration defaultColorSelectorConfiguration;
0141 
0142 private:
0143     /*mutable*/ KConfigGroup m_cfg;
0144     bool m_readOnly;
0145 };
0146 
0147 typedef WGConfig Accessor;
0148 
0149 class WGConfigNotifier : public QObject
0150 {
0151     Q_OBJECT
0152 public:
0153     WGConfigNotifier() = default;
0154     WGConfigNotifier(const WGConfigNotifier&) = delete;
0155     ~WGConfigNotifier() override = default;
0156 
0157     WGConfigNotifier operator=(const WGConfigNotifier&) = delete;
0158 
0159     /**
0160      * Notify that the plugin configuration has changed. This will cause the
0161      * configChanged() signal to be emitted.
0162      */
0163     void notifyConfigChanged();
0164     /**
0165      * Notify that a setting which affects KisVisualColorSelector or the
0166      * KisVisualColorModel it uses has changed.
0167      */
0168     void notifySelectorConfigChanged();
0169 
0170 Q_SIGNALS:
0171     /**
0172      * This signal is emitted whenever notifyConfigChanged() is called.
0173      */
0174     void configChanged();
0175     void selectorConfigChanged();
0176 };
0177 
0178 /**
0179  * @return the WGConfigNotifier singleton
0180  */
0181 WGConfigNotifier* notifier();
0182 
0183 /* ======== Configuration object definitions ========
0184 /  TODO: Think about splitting this off into individual headers
0185 /  to prevent full recompile on every change.
0186 */
0187 
0188 enum Scrolling {
0189     ScrollNone,
0190     ScrollLongitudinal,
0191     ScrollLaterally
0192 };
0193 
0194 struct ColorPatches
0195 {
0196     NumericSetting<Qt::Orientation> orientation;
0197     NumericSetting<QSize> patchSize;
0198     NumericSetting<int> maxCount;
0199     NumericSetting<int> rows;
0200     NumericSetting<Scrolling> scrolling;
0201 };
0202 
0203 extern const ColorPatches colorHistory;
0204 extern const ColorPatches commonColors;
0205 extern const ColorPatches popupPatches;
0206 
0207 extern const GenericSetting<bool> proofToPaintingColors;
0208 extern const GenericSetting<bool> colorHistoryEnabled;
0209 extern const GenericSetting<bool> commonColorsEnabled;
0210 extern const GenericSetting<bool> colorHistoryShowClearButton;
0211 extern const GenericSetting<bool> commonColorsAutoUpdate;
0212 
0213 extern const GenericSetting<bool> quickSettingsEnabled;
0214 extern const NumericSetting<int> popupSize;
0215 
0216 // Shade Selector
0217 extern const NumericSetting<int> shadeSelectorLineHeight;
0218 extern const GenericSetting<bool> shadeSelectorUpdateOnExternalChanges;
0219 extern const GenericSetting<bool> shadeSelectorUpdateOnInteractionEnd;
0220 extern const GenericSetting<bool> shadeSelectorUpdateOnRightClick;
0221 
0222 } // namespace WGConfig
0223 
0224 #endif // WGCONFIG_H