File indexing completed on 2024-12-22 04:15:03

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 #include "WGConfigSelectorTypes.h"
0008 
0009 #include <kconfig.h>
0010 #include <kis_debug.h>
0011 #include <KoColorProfile.h>
0012 #include <KoColorSpaceRegistry.h>
0013 
0014 #include <QApplication>
0015 #include <QGlobalStatic>
0016 #include <QStringList>
0017 #include <QTextStream>
0018 #include <QThread>
0019 
0020 namespace WGConfig {
0021 
0022 Q_GLOBAL_STATIC(WGConfigNotifier, s_notifier_instance)
0023 
0024 WGConfig::WGConfig(bool readOnly)
0025     : m_cfg( KSharedConfig::openConfig()->group(configGroupName()))
0026     , m_readOnly(readOnly)
0027 {
0028     if (!readOnly) {
0029         KIS_SAFE_ASSERT_RECOVER_RETURN(qApp && qApp->thread() == QThread::currentThread());
0030     }
0031 }
0032 
0033 WGConfig::~WGConfig()
0034 {
0035     if (m_readOnly) return;
0036 
0037     if (qApp && qApp->thread() != QThread::currentThread()) {
0038         dbgKrita << "WARNING: WGConfig: requested config synchronization from nonGUI thread! Called from:" << kisBacktrace();
0039         return;
0040     }
0041 
0042     m_cfg.sync();
0043 }
0044 
0045 QString WGConfig::configGroupName()
0046 {
0047     return QStringLiteral("WideGamutColorSelector");
0048 }
0049 
0050 KisColorSelectorConfiguration WGConfig::colorSelectorConfiguration() const
0051 {
0052     QString config = m_cfg.readEntry("colorSelectorConfiguration", QString());
0053     return config.isEmpty() ? defaultColorSelectorConfiguration : KisColorSelectorConfiguration(config);
0054 }
0055 
0056 void WGConfig::setColorSelectorConfiguration(const KisColorSelectorConfiguration &config)
0057 {
0058     m_cfg.writeEntry("colorSelectorConfiguration", config.toString());
0059 }
0060 
0061 QVector<KisColorSelectorConfiguration> WGConfig::favoriteConfigurations(bool defaultValue) const
0062 {
0063     if (defaultValue) {
0064         return defaultFavoriteConfigurations();
0065     }
0066 
0067     QVector<KisColorSelectorConfiguration> favoriteConfigs;
0068     QString favorites = m_cfg.readEntry("favoriteSelectorConfigurations", QString());
0069     if (favorites.isEmpty()) {
0070         return defaultFavoriteConfigurations();
0071     }
0072     QStringList favoriteList(favorites.split(';'));
0073     for (QString &fav: favoriteList) {
0074         favoriteConfigs.append(KisColorSelectorConfiguration(fav));
0075     }
0076     return favoriteConfigs;
0077 }
0078 
0079 QVector<KisColorSelectorConfiguration> WGConfig::defaultFavoriteConfigurations()
0080 {
0081     using KCSC = KisColorSelectorConfiguration;
0082     QVector<KCSC> defaults;
0083     defaults.append(KCSC(KCSC::Triangle, KCSC::Ring, KCSC::SV, KCSC::H));
0084     defaults.append(KCSC(KCSC::Square, KCSC::Ring, KCSC::SV, KCSC::H));
0085     defaults.append(KCSC(KCSC::Wheel, KCSC::Slider, KCSC::VH, KCSC::hsvS));
0086     return defaults;
0087 }
0088 
0089 void WGConfig::setFavoriteConfigurations(const QVector<KisColorSelectorConfiguration> &favoriteConfigs)
0090 {
0091     QStringList favoriteList;
0092     for (const KisColorSelectorConfiguration &fav: favoriteConfigs) {
0093         favoriteList.append(fav.toString());
0094     }
0095     m_cfg.writeEntry("favoriteSelectorConfigurations", favoriteList.join(';'));
0096 }
0097 
0098 QVector<ShadeLine> WGConfig::defaultShadeSelectorLines()
0099 {
0100     QVector<ShadeLine> defaultLines;
0101     defaultLines.append(ShadeLine(QVector4D(0.3, 0, 0, 0)));
0102     defaultLines.append(ShadeLine(QVector4D(0, -0.5, 0, 0)));
0103     defaultLines.append(ShadeLine(QVector4D(0, 0, 0.5, 0)));
0104     defaultLines.append(ShadeLine(QVector4D(0, -0.2, 0.2, 0)));
0105     return defaultLines;
0106 }
0107 
0108 QVector<ShadeLine> WGConfig::shadeSelectorLines(bool defaultValue) const
0109 {
0110     if (defaultValue) {
0111         return defaultShadeSelectorLines();
0112     }
0113 
0114     QString configString = m_cfg.readEntry("minimalShadeSelectorLines", QString());
0115     if (configString.isEmpty()) {
0116         return defaultShadeSelectorLines();
0117     }
0118     QVector<ShadeLine> shadeLines;
0119     QStringList shadeLineList(configString.split('|'));
0120     for (const QString &line: qAsConst(shadeLineList)) {
0121         QVector4D gradient, offset;
0122         int patchCount = -1;
0123         QStringList values = line.split(';');
0124         if (values.size() >= 4) {
0125             for (int i = 0; i < 4; i++) {
0126                 gradient[i] = qBound(-1.0f, values.at(i).toFloat(), 1.0f);
0127             }
0128         }
0129         if (values.size() >= 8) {
0130             for (int i = 0; i < 4; i++) {
0131                 offset[i] = qBound(-1.0f, values.at(i + 4).toFloat(), 1.0f);
0132             }
0133         }
0134         if (values.size() >= 9) {
0135             patchCount = qBound(-1, values.at(8).toInt(), 99);
0136         }
0137         shadeLines.append(ShadeLine(gradient, offset, patchCount));
0138     }
0139     return shadeLines;
0140 }
0141 
0142 void WGConfig::setShadeSelectorLines(const QVector<ShadeLine> &shadeLines)
0143 {
0144     QStringList shadeLineList;
0145     for (const ShadeLine &line: shadeLines) {
0146         QString lineString;
0147         QTextStream stream(&lineString);
0148         for (int i = 0; i < 4; i++) {
0149             stream << line.gradient[i] << ';';
0150         }
0151         for (int i = 0; i < 4; i++) {
0152             stream << line.offset[i] << ';';
0153         }
0154         stream << line.patchCount;
0155         shadeLineList.append(lineString);
0156     }
0157     m_cfg.writeEntry("minimalShadeSelectorLines", shadeLineList.join('|'));
0158 }
0159 
0160 const KoColorSpace* WGConfig::customSelectionColorSpace(bool defaultValue) const
0161 {
0162     const KoColorSpace *cs = 0;
0163 
0164     if (!defaultValue) {
0165         QString modelID = m_cfg.readEntry("customColorSpaceModel", "RGBA");
0166         QString depthID = m_cfg.readEntry("customColorSpaceDepthID", "U8");
0167         QString profile = m_cfg.readEntry("customColorSpaceProfile", "");
0168 
0169         cs = KoColorSpaceRegistry::instance()->colorSpace(modelID, depthID, profile);
0170     }
0171 
0172     if (!cs) {
0173         cs = KoColorSpaceRegistry::instance()->rgb8();
0174     }
0175 
0176     return cs;
0177 }
0178 
0179 void WGConfig::setCustomSelectionColorSpace(const KoColorSpace *cs)
0180 {
0181     if(cs) {
0182         m_cfg.writeEntry("customColorSpaceModel", cs->colorModelId().id());
0183         m_cfg.writeEntry("customColorSpaceDepthID", cs->colorDepthId().id());
0184         if (cs->profile()) {
0185             m_cfg.writeEntry("customColorSpaceProfile", cs->profile()->name());
0186         }
0187     }
0188 }
0189 
0190 WGConfigNotifier *notifier()
0191 {
0192     return s_notifier_instance;
0193 }
0194 
0195 const KisColorSelectorConfiguration WGConfig::defaultColorSelectorConfiguration =
0196         KisColorSelectorConfiguration(KisColorSelectorConfiguration::Triangle,
0197                                       KisColorSelectorConfiguration::Ring,
0198                                       KisColorSelectorConfiguration::SV,
0199                                       KisColorSelectorConfiguration::H);
0200 
0201 void WGConfigNotifier::notifyConfigChanged()
0202 {
0203     emit configChanged();
0204 }
0205 
0206 void WGConfigNotifier::notifySelectorConfigChanged()
0207 {
0208     emit selectorConfigChanged();
0209 }
0210 
0211 // ======== Static Configuration Object Instantiation ========
0212 
0213 const ColorPatches colorHistory {
0214     { "colorHistory.orientation", Qt::Horizontal, Qt::Horizontal, Qt::Vertical, true },
0215     { "colorHistory.patchSize", QSize(16,16), QSize(10,10), QSize(99,99), true },
0216     { "colorHistory.maxCount", 30, 2, 200, true },
0217     { "colorHistory.rows", 1, 1, 20, true },
0218     { "colorHistory.scrolling", ScrollLongitudinal, ScrollNone, ScrollLaterally, true }
0219 };
0220 
0221 const ColorPatches commonColors {
0222     { "commonColors.orientation", Qt::Horizontal, Qt::Horizontal, Qt::Vertical, true },
0223     { "commonColors.patchSize", QSize(16,16), QSize(10,10), QSize(99,99), true },
0224     { "commonColors.maxCount", 20, 2, 200, true },
0225     { "commonColors.rows", 1, 1, 20, true },
0226     { "commonColors.scrolling", ScrollLongitudinal, ScrollNone, ScrollLaterally, true }
0227 };
0228 
0229 const ColorPatches popupPatches {
0230     { "popupColorPatchOrientation", Qt::Horizontal, Qt::Horizontal, Qt::Vertical, true },
0231     { "popupColorPatchSize", QSize(32,32), QSize(10,10), QSize(99,99), true },
0232     { "popupPatches.maxCount", 30, 2, 200, true },
0233     { "popupPatches.rows", 1, 1, 20, true },
0234     { "popupPatches.scrolling", ScrollLongitudinal, ScrollNone, ScrollLaterally, true }
0235 };
0236 
0237 const GenericSetting<bool> proofToPaintingColors {"proofToPaintingColors", false};
0238 const GenericSetting<bool> colorHistoryEnabled {"colorHistoryEnabled", true};
0239 const GenericSetting<bool> commonColorsEnabled {"commonColorsEnabled", true};
0240 const GenericSetting<bool> colorHistoryShowClearButton { "colorHistoryShowClearButton", false };
0241 const GenericSetting<bool> commonColorsAutoUpdate { "commonColorsAutoUpdate", false };
0242 
0243 const GenericSetting<bool> quickSettingsEnabled { "quickSettingsMenuEnabled", true };
0244 const NumericSetting<int> popupSize { "popupSize", 300, 100, 500, true };
0245 
0246 const NumericSetting<int> shadeSelectorLineHeight { "shadeSelectorLineHeight", 10, 8, 99 };
0247 const GenericSetting<bool> shadeSelectorUpdateOnExternalChanges { "shadeSelectorUpdateOnExternalChanges", true };
0248 const GenericSetting<bool> shadeSelectorUpdateOnInteractionEnd { "shadeSelectorUpdateOnInteractionEnd", false };
0249 const GenericSetting<bool> shadeSelectorUpdateOnRightClick { "shadeSelectorUpdateOnRightClick", true };
0250 
0251 const NumericSetting<KisVisualColorModel::ColorModel> rgbColorModel {
0252     "rgbColorModel", KisVisualColorModel::HSV, KisVisualColorModel::HSV, KisVisualColorModel::HSY, true
0253 };
0254 const NumericSetting<KisVisualColorSelector::RenderMode> selectorRenderMode {
0255     "renderMode", KisVisualColorSelector::DynamicBackground, KisVisualColorSelector::StaticBackground, KisVisualColorSelector::CompositeBackground, true
0256 };
0257 
0258 } // namespace WGConfig