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