Changeset View
Changeset View
Standalone View
Standalone View
libs/image/kis_image_config.h
Show All 17 Lines | |||||
18 | 18 | | |||
19 | #ifndef KIS_IMAGE_CONFIG_H_ | 19 | #ifndef KIS_IMAGE_CONFIG_H_ | ||
20 | #define KIS_IMAGE_CONFIG_H_ | 20 | #define KIS_IMAGE_CONFIG_H_ | ||
21 | 21 | | |||
22 | #include <kconfiggroup.h> | 22 | #include <kconfiggroup.h> | ||
23 | #include "kritaimage_export.h" | 23 | #include "kritaimage_export.h" | ||
24 | #include "KisProofingConfiguration.h" | 24 | #include "KisProofingConfiguration.h" | ||
25 | #include "kis_types.h" | 25 | #include "kis_types.h" | ||
26 | #include "kis_global.h" | ||||
26 | 27 | | |||
27 | class KRITAIMAGE_EXPORT KisImageConfig | 28 | #include <QThread> | ||
29 | #include "KoColorProfile.h" | ||||
30 | #include <KisKConfigWrapper.h> | ||||
31 | | ||||
32 | #define DECL_PROPERTY_RW(getter, Type, defValue, setter) \ | ||||
rempt: Hm... There's already Q_DECL_*, should we namespace our DECL_* with KIS_ ? Also, DECL_PROPERTY… | |||||
33 | Type getter(bool requestDefault = false) const { \ | ||||
34 | return !requestDefault ? \ | ||||
35 | Type(m_config.readEntry(#getter, defValue)) : Type(defValue); \ | ||||
36 | } \ | ||||
37 | void setter(Type value) { \ | ||||
38 | m_config.writeEntry(#getter, value); \ | ||||
39 | } | ||||
40 | | ||||
41 | #define DECL_PROPERTY_R(getter, Type, defValue) \ | ||||
42 | Type getter(bool requestDefault = false) const { \ | ||||
43 | return !requestDefault ? \ | ||||
44 | Type(m_config.readEntry(#getter, defValue)) : Type(defValue); \ | ||||
45 | } | ||||
46 | | ||||
47 | | ||||
48 | namespace KisImageConfigImplPrivate | ||||
28 | { | 49 | { | ||
29 | public: | 50 | int KRITAIMAGE_EXPORT totalRAM(); // MiB | ||
30 | KisImageConfig(bool readOnly); | 51 | QString KRITAIMAGE_EXPORT safelyGetWritableTempLocation(const QString &suffix, const QString &userValue, bool requestDefault); | ||
31 | ~KisImageConfig(); | 52 | } | ||
32 | 53 | | |||
33 | bool enableProgressReporting(bool requestDefault = false) const; | | |||
34 | void setEnableProgressReporting(bool value); | | |||
35 | 54 | | |||
36 | bool enablePerfLog(bool requestDefault = false) const; | 55 | template<class ConfigClass> | ||
37 | void setEnablePerfLog(bool value); | 56 | class KRITAIMAGE_EXPORT KisImageConfigImpl | ||
57 | { | ||||
58 | public: | ||||
59 | KisImageConfigImpl(); | ||||
38 | 60 | | |||
39 | qreal transformMaskOffBoundsReadArea() const; | 61 | DECL_PROPERTY_RW(enableProgressReporting, bool, true, setEnableProgressReporting) | ||
62 | DECL_PROPERTY_RW(enablePerfLog, bool, false, setEnablePerfLog) | ||||
63 | DECL_PROPERTY_R(transformMaskOffBoundsReadArea, qreal, 0.5) | ||||
64 | DECL_PROPERTY_RW(updatePatchHeight, int, 512, setUpdatePatchHeight) | ||||
65 | DECL_PROPERTY_RW(updatePatchWidth, int, 512, setUpdatePatchWidth) | ||||
40 | 66 | | |||
41 | int updatePatchHeight() const; | 67 | DECL_PROPERTY_R(maxCollectAlpha, qreal, 2.5) | ||
42 | void setUpdatePatchHeight(int value); | 68 | DECL_PROPERTY_R(maxMergeAlpha, qreal, 1.0) | ||
43 | int updatePatchWidth() const; | 69 | DECL_PROPERTY_R(maxMergeCollectAlpha, qreal, 1.5) | ||
44 | void setUpdatePatchWidth(int value); | 70 | DECL_PROPERTY_RW(schedulerBalancingRatio, qreal, 100, setSchedulerBalancingRatio) | ||
45 | 71 | | |||
46 | qreal maxCollectAlpha() const; | 72 | DECL_PROPERTY_RW(maxSwapSize, int, 4096, setMaxSwapSize) // in MiB | ||
47 | qreal maxMergeAlpha() const; | 73 | DECL_PROPERTY_RW(swapSlabSize, int, 64, setSwapSlabSize) // in MiB | ||
48 | qreal maxMergeCollectAlpha() const; | 74 | DECL_PROPERTY_RW(swapWindowSize, int, 16, setSwapWindowSize) // in MiB | ||
49 | qreal schedulerBalancingRatio() const; | | |||
50 | void setSchedulerBalancingRatio(qreal value); | | |||
51 | 75 | | |||
52 | int maxSwapSize(bool requestDefault = false) const; | 76 | DECL_PROPERTY_RW(memoryHardLimitPercent, qreal, 50.0, setMemoryHardLimitPercent) | ||
53 | void setMaxSwapSize(int value); | 77 | DECL_PROPERTY_RW(memorySoftLimitPercent, qreal, 2.0, setMemorySoftLimitPercent) | ||
78 | DECL_PROPERTY_RW(memoryPoolLimitPercent, qreal, 0.0, setMemoryPoolLimitPercent) | ||||
54 | 79 | | |||
55 | int swapSlabSize() const; | 80 | DECL_PROPERTY_RW(numberOfOnionSkins, int, 10, setNumberOfOnionSkins) | ||
56 | void setSwapSlabSize(int value); | 81 | DECL_PROPERTY_RW(onionSkinTintFactor, int, 192, setOnionSkinTintFactor) | ||
57 | 82 | | |||
58 | int swapWindowSize() const; | 83 | DECL_PROPERTY_RW(onionSkinTintColorBackward, QColor, QColor(Qt::red), setOnionSkinTintColorBackward) | ||
59 | void setSwapWindowSize(int value); | 84 | DECL_PROPERTY_RW(onionSkinTintColorForward, QColor, QColor(Qt::green), setOnionSkinTintColorForward) | ||
85 | DECL_PROPERTY_RW(lazyFrameCreationEnabled, bool, true, setLazyFrameCreationEnabled) | ||||
86 | DECL_PROPERTY_RW(showAdditionalOnionSkinsSettings, bool, true, setShowAdditionalOnionSkinsSettings) | ||||
87 | DECL_PROPERTY_RW(defaultFrameColorLabel, int, 0, setDefaultFrameColorLabel) | ||||
60 | 88 | | |||
61 | int tilesHardLimit() const; // MiB | 89 | DECL_PROPERTY_RW(fpsLimit, int, 100, setFpsLimit) | ||
62 | int tilesSoftLimit() const; // MiB | 90 | DECL_PROPERTY_RW(useOnDiskAnimationCacheSwapping, bool, true, setUseOnDiskAnimationCacheSwapping) | ||
63 | int poolLimit() const; // MiB | 91 | DECL_PROPERTY_RW(useAnimationCacheFrameSizeLimit, bool, true, setUseAnimationCacheFrameSizeLimit) | ||
92 | DECL_PROPERTY_RW(animationCacheFrameSizeLimit, int, 2500, setAnimationCacheFrameSizeLimit) | ||||
93 | DECL_PROPERTY_RW(useAnimationCacheRegionOfInterest, bool, true, setUseAnimationCacheRegionOfInterest) | ||||
64 | 94 | | |||
65 | qreal memoryHardLimitPercent(bool requestDefault = false) const; // % of total RAM | 95 | DECL_PROPERTY_RW(animationCacheRegionOfInterestMargin, qreal, 0.25, setAnimationCacheRegionOfInterestMargin) | ||
66 | qreal memorySoftLimitPercent(bool requestDefault = false) const; // % of memoryHardLimitPercent() * (1 - 0.01 * memoryPoolLimitPercent()) | 96 | DECL_PROPERTY_RW(selectionOverlayMaskColor, QColor, QColor(255, 0, 0, 220), setSelectionOverlayMaskColor) | ||
67 | qreal memoryPoolLimitPercent(bool requestDefault = false) const; // % of memoryHardLimitPercent() | | |||
68 | void setMemoryHardLimitPercent(qreal value); | | |||
69 | void setMemorySoftLimitPercent(qreal value); | | |||
70 | void setMemoryPoolLimitPercent(qreal value); | | |||
71 | 97 | | |||
72 | static int totalRAM(); // MiB | 98 | DECL_PROPERTY_RW(useLodForColorizeMask, bool, false, setUseLodForColorizeMask) | ||
73 | 99 | | |||
74 | /** | | |||
75 | * @return a specific directory for the swapfile, if set. If not set, return an | | |||
76 | * empty QString and use the default KDE directory. | | |||
77 | */ | | |||
78 | QString swapDir(bool requestDefault = false); | | |||
79 | void setSwapDir(const QString &swapDir); | | |||
80 | 100 | | |||
81 | int numberOfOnionSkins() const; | 101 | int tilesHardLimit() const | ||
82 | void setNumberOfOnionSkins(int value); | 102 | { | ||
103 | qreal hp = qreal(memoryHardLimitPercent()) / 100.0; | ||||
104 | qreal pp = qreal(memoryPoolLimitPercent()) / 100.0; | ||||
105 | | ||||
106 | return KisImageConfigImplPrivate::totalRAM() * hp * (1 - pp); | ||||
107 | } | ||||
83 | 108 | | |||
84 | int onionSkinTintFactor() const; | 109 | int tilesSoftLimit() const | ||
85 | void setOnionSkinTintFactor(int value); | 110 | { | ||
111 | qreal sp = qreal(memorySoftLimitPercent()) / 100.0; | ||||
86 | 112 | | |||
87 | int onionSkinOpacity(int offset) const; | 113 | return tilesHardLimit() * sp; | ||
88 | void setOnionSkinOpacity(int offset, int value); | 114 | } | ||
89 | 115 | | |||
90 | bool onionSkinState(int offset) const; | 116 | int poolLimit() const | ||
91 | void setOnionSkinState(int offset, bool value); | 117 | { | ||
118 | qreal hp = qreal(memoryHardLimitPercent()) / 100.0; | ||||
119 | qreal pp = qreal(memoryPoolLimitPercent()) / 100.0; | ||||
92 | 120 | | |||
93 | QColor onionSkinTintColorBackward() const; | 121 | return KisImageConfigImplPrivate::totalRAM() * hp * pp; | ||
94 | void setOnionSkinTintColorBackward(const QColor &value); | 122 | } | ||
95 | 123 | | |||
96 | QColor onionSkinTintColorForward() const; | 124 | static int totalRAM() { | ||
97 | void setOnionSkinTintColorForward(const QColor &value); | 125 | return KisImageConfigImplPrivate::totalRAM(); // in MiB | ||
126 | } | ||||
98 | 127 | | |||
99 | bool lazyFrameCreationEnabled(bool requestDefault = false) const; | 128 | /** | ||
100 | void setLazyFrameCreationEnabled(bool value); | 129 | * @return a specific directory for the swapfile, if set. If not set, | ||
130 | * returns system's temporary writable location | ||||
131 | */ | ||||
132 | QString swapDir(bool requestDefault = false) { | ||||
133 | const QString configuredValue = m_config.readEntry("swaplocation", ""); | ||||
134 | return KisImageConfigImplPrivate::safelyGetWritableTempLocation("swap", configuredValue, requestDefault); | ||||
135 | } | ||||
136 | | ||||
137 | void setSwapDir(const QString &swapDir) { | ||||
138 | m_config.writeEntry("swaplocation", swapDir); | ||||
139 | } | ||||
101 | 140 | | |||
102 | bool showAdditionalOnionSkinsSettings(bool requestDefault = false) const; | 141 | int onionSkinOpacity(int offset) const | ||
103 | void setShowAdditionalOnionSkinsSettings(bool value); | 142 | { | ||
143 | int value = m_config.readEntry("onionSkinOpacity_" + QString::number(offset), -1); | ||||
104 | 144 | | |||
105 | int defaultFrameColorLabel() const; | 145 | if (value < 0) { | ||
106 | void setDefaultFrameColorLabel(int label); | 146 | const int num = numberOfOnionSkins(); | ||
147 | const qreal dx = qreal(qAbs(offset)) / num; | ||||
148 | value = 0.7 * exp(-pow2(dx) / 0.5) * 255; | ||||
149 | } | ||||
107 | 150 | | |||
108 | KisProofingConfigurationSP defaultProofingconfiguration(); | 151 | return value; | ||
109 | void setDefaultProofingConfig(const KoColorSpace *proofingSpace, int proofingIntent, bool blackPointCompensation, KoColor warningColor, double adaptationState); | 152 | } | ||
110 | 153 | | |||
111 | bool useLodForColorizeMask(bool requestDefault = false) const; | 154 | void setOnionSkinOpacity(int offset, int value) | ||
112 | void setUseLodForColorizeMask(bool value); | 155 | { | ||
156 | m_config.writeEntry("onionSkinOpacity_" + QString::number(offset), value); | ||||
157 | } | ||||
113 | 158 | | |||
114 | int maxNumberOfThreads(bool defaultValue = false) const; | 159 | bool onionSkinState(int offset) const | ||
115 | void setMaxNumberOfThreads(int value); | 160 | { | ||
161 | bool enableByDefault = (qAbs(offset) <= 2); | ||||
162 | return m_config.readEntry("onionSkinState_" + QString::number(offset), enableByDefault); | ||||
163 | } | ||||
116 | 164 | | |||
117 | int frameRenderingClones(bool defaultValue = false) const; | 165 | void setOnionSkinState(int offset, bool value) | ||
118 | void setFrameRenderingClones(int value); | 166 | { | ||
167 | m_config.writeEntry("onionSkinState_" + QString::number(offset), value); | ||||
168 | } | ||||
119 | 169 | | |||
120 | int fpsLimit(bool defaultValue = false) const; | 170 | KisProofingConfigurationSP defaultProofingconfiguration() | ||
121 | void setFpsLimit(int value); | 171 | { | ||
172 | KisProofingConfiguration *proofingConfig= new KisProofingConfiguration(); | ||||
173 | proofingConfig->proofingProfile = m_config.readEntry("defaultProofingProfileName", "Chemical proof"); | ||||
174 | proofingConfig->proofingModel = m_config.readEntry("defaultProofingProfileModel", "CMYKA"); | ||||
175 | proofingConfig->proofingDepth = m_config.readEntry("defaultProofingProfileDepth", "U8"); | ||||
176 | proofingConfig->intent = (KoColorConversionTransformation::Intent)m_config.readEntry("defaultProofingProfileIntent", 3); | ||||
177 | if (m_config.readEntry("defaultProofingBlackpointCompensation", true)) { | ||||
178 | proofingConfig->conversionFlags |= KoColorConversionTransformation::ConversionFlag::BlackpointCompensation; | ||||
179 | } else { | ||||
180 | proofingConfig->conversionFlags = proofingConfig->conversionFlags & ~KoColorConversionTransformation::ConversionFlag::BlackpointCompensation; | ||||
181 | } | ||||
182 | QColor def(Qt::green); | ||||
183 | m_config.readEntry("defaultProofingGamutwarning", def); | ||||
184 | KoColor col(KoColorSpaceRegistry::instance()->rgb8()); | ||||
185 | col.fromQColor(def); | ||||
186 | col.setOpacity(1.0); | ||||
187 | proofingConfig->warningColor = col; | ||||
188 | proofingConfig->adaptationState = (double)m_config.readEntry("defaultProofingAdaptationState", 1.0); | ||||
189 | return toQShared(proofingConfig); | ||||
190 | } | ||||
122 | 191 | | |||
123 | bool useOnDiskAnimationCacheSwapping(bool defaultValue = false) const; | 192 | void setDefaultProofingConfig(const KoColorSpace *proofingSpace, int proofingIntent, bool blackPointCompensation, KoColor warningColor, double adaptationState) | ||
124 | void setUseOnDiskAnimationCacheSwapping(bool value); | 193 | { | ||
194 | m_config.writeEntry("defaultProofingProfileName", proofingSpace->profile()->name()); | ||||
195 | m_config.writeEntry("defaultProofingProfileModel", proofingSpace->colorModelId().id()); | ||||
196 | m_config.writeEntry("defaultProofingProfileDepth", proofingSpace->colorDepthId().id()); | ||||
197 | m_config.writeEntry("defaultProofingProfileIntent", proofingIntent); | ||||
198 | m_config.writeEntry("defaultProofingBlackpointCompensation", blackPointCompensation); | ||||
199 | QColor c; | ||||
200 | c = warningColor.toQColor(); | ||||
201 | m_config.writeEntry("defaultProofingGamutwarning", c); | ||||
202 | m_config.writeEntry("defaultProofingAdaptationState",adaptationState); | ||||
203 | } | ||||
125 | 204 | | |||
126 | QString animationCacheDir(bool defaultValue = false) const; | 205 | int maxNumberOfThreads(bool requestDefalt = false) const | ||
127 | void setAnimationCacheDir(const QString &value); | 206 | { | ||
207 | return (requestDefalt ? QThread::idealThreadCount() : m_config.readEntry("maxNumberOfThreads", QThread::idealThreadCount())); | ||||
208 | } | ||||
128 | 209 | | |||
129 | bool useAnimationCacheFrameSizeLimit(bool defaultValue = false) const; | 210 | void setMaxNumberOfThreads(int value) | ||
130 | void setUseAnimationCacheFrameSizeLimit(bool value); | 211 | { | ||
212 | if (value == QThread::idealThreadCount()) { | ||||
213 | m_config.deleteEntry("maxNumberOfThreads"); | ||||
214 | } else { | ||||
215 | m_config.writeEntry("maxNumberOfThreads", value); | ||||
216 | } | ||||
217 | } | ||||
131 | 218 | | |||
132 | int animationCacheFrameSizeLimit(bool defaultValue = false) const; | 219 | int frameRenderingClones(bool requestDefalt = false) const | ||
133 | void setAnimationCacheFrameSizeLimit(int value); | 220 | { | ||
221 | const int defaultClonesCount = qMax(1, maxNumberOfThreads(requestDefalt) / 2); | ||||
222 | return requestDefalt ? defaultClonesCount : m_config.readEntry("frameRenderingClones", defaultClonesCount); | ||||
223 | } | ||||
134 | 224 | | |||
135 | bool useAnimationCacheRegionOfInterest(bool defaultValue = false) const; | 225 | void setFrameRenderingClones(int value) | ||
136 | void setUseAnimationCacheRegionOfInterest(bool value); | 226 | { | ||
227 | m_config.writeEntry("frameRenderingClones", value); | ||||
228 | } | ||||
137 | 229 | | |||
138 | qreal animationCacheRegionOfInterestMargin(bool defaultValue = false) const; | 230 | QString animationCacheDir(bool requestDefalt = false) const | ||
139 | void setAnimationCacheRegionOfInterestMargin(qreal value); | 231 | { | ||
232 | const QString configuredValue = m_config.readValue("animationCacheDir", ""); | ||||
233 | return KisImageConfigImplPrivate::safelyGetWritableTempLocation("animation_cache", configuredValue, requestDefalt); | ||||
234 | } | ||||
140 | 235 | | |||
141 | QColor selectionOverlayMaskColor(bool defaultValue = false) const; | 236 | void setAnimationCacheDir(const QString &value) | ||
142 | void setSelectionOverlayMaskColor(const QColor &color); | 237 | { | ||
238 | m_config.writeEntry("animationCacheDir", value); | ||||
239 | } | ||||
143 | 240 | | |||
144 | private: | 241 | private: | ||
145 | Q_DISABLE_COPY(KisImageConfig) | 242 | Q_DISABLE_COPY(KisImageConfigImpl) | ||
146 | | ||||
147 | QString safelyGetWritableTempLocation(const QString &suffix, const QString &configKey, bool requestDefault) const; | | |||
148 | 243 | | |||
149 | private: | 244 | private: | ||
150 | KConfigGroup m_config; | 245 | ConfigClass m_config; | ||
151 | bool m_readOnly; | | |||
152 | }; | 246 | }; | ||
153 | 247 | | |||
248 | using KisImageConfig = KisImageConfigImpl<KisKConfigWrapper>; | ||||
249 | using KisImageConfigMutable = KisImageConfigImpl<KisKConfigMutableWrapper>; | ||||
154 | 250 | | |||
155 | #endif /* KIS_IMAGE_CONFIG_H_ */ | 251 | #endif /* KIS_IMAGE_CONFIG_H_ */ | ||
156 | 252 | |
Hm... There's already Q_DECL_*, should we namespace our DECL_* with KIS_ ? Also, DECL_PROPERTY sounds a bit like Q_PROPERTY, but that's different. KIS_CONFIG_GETTER and KIS_CONFIG_GETTER_SETTER might be clearer?