1 /*
2 * Copyright (c) 2010 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "kis_image_config.h"
20
21 #include <ksharedconfig.h>
22
23 #include <KoConfig.h>
24 #include <KoColorProfile.h>
25 #include <KoColorSpaceRegistry.h>
26 #include <KoColorConversionTransformation.h>
27
28 #include "kis_debug.h"
29
30 #include <QThread>
31 #include <QApplication>
32 #include <QColor>
33 #include <QDir>
34
35 #include "kis_global.h"
36 #include <cmath>
37 #include <QTemporaryFile>
38
39 #ifdef Q_OS_MACOS
40 #include <errno.h>
41 #endif
42
43 #ifdef Q_OS_FREEBSD
44 #include <sys/types.h>
45 #include <sys/sysctl.h>
46 #endif
47
KisImageConfig(bool readOnly)48 KisImageConfig::KisImageConfig(bool readOnly)
49 : m_config(KSharedConfig::openConfig()->group(QString()))
50 , m_readOnly(readOnly)
51 {
52 if (!readOnly) {
53 KIS_SAFE_ASSERT_RECOVER_RETURN(qApp->thread() == QThread::currentThread());
54 }
55 #ifdef Q_OS_MACOS
56 // clear /var/folders/ swap path set by old broken Krita swap implementation in order to use new default swap dir.
57 QString swap = m_config.readEntry("swaplocation", "");
58 if (swap.startsWith("/var/folders/")) {
59 m_config.deleteEntry("swaplocation");
60 }
61 #endif
62 }
63
~KisImageConfig()64 KisImageConfig::~KisImageConfig()
65 {
66 if (m_readOnly) return;
67
68 if (qApp->thread() != QThread::currentThread()) {
69 dbgKrita << "KisImageConfig: requested config synchronization from nonGUI thread! Called from" << kisBacktrace();
70 return;
71 }
72
73 m_config.sync();
74 }
75
enableProgressReporting(bool requestDefault) const76 bool KisImageConfig::enableProgressReporting(bool requestDefault) const
77 {
78 return !requestDefault ?
79 m_config.readEntry("enableProgressReporting", true) : true;
80 }
81
setEnableProgressReporting(bool value)82 void KisImageConfig::setEnableProgressReporting(bool value)
83 {
84 m_config.writeEntry("enableProgressReporting", value);
85 }
86
enablePerfLog(bool requestDefault) const87 bool KisImageConfig::enablePerfLog(bool requestDefault) const
88 {
89 return !requestDefault ?
90 m_config.readEntry("enablePerfLog", false) :false;
91 }
92
setEnablePerfLog(bool value)93 void KisImageConfig::setEnablePerfLog(bool value)
94 {
95 m_config.writeEntry("enablePerfLog", value);
96 }
97
transformMaskOffBoundsReadArea() const98 qreal KisImageConfig::transformMaskOffBoundsReadArea() const
99 {
100 return m_config.readEntry("transformMaskOffBoundsReadArea", 0.5);
101 }
102
updatePatchHeight() const103 int KisImageConfig::updatePatchHeight() const
104 {
105 int patchHeight = m_config.readEntry("updatePatchHeight", 512);
106 if (patchHeight <= 0) return 512;
107 return patchHeight;
108 }
109
setUpdatePatchHeight(int value)110 void KisImageConfig::setUpdatePatchHeight(int value)
111 {
112 m_config.writeEntry("updatePatchHeight", value);
113 }
114
updatePatchWidth() const115 int KisImageConfig::updatePatchWidth() const
116 {
117 int patchWidth = m_config.readEntry("updatePatchWidth", 512);
118 if (patchWidth <= 0) return 512;
119 return patchWidth;
120 }
121
setUpdatePatchWidth(int value)122 void KisImageConfig::setUpdatePatchWidth(int value)
123 {
124 m_config.writeEntry("updatePatchWidth", value);
125 }
126
maxCollectAlpha() const127 qreal KisImageConfig::maxCollectAlpha() const
128 {
129 return m_config.readEntry("maxCollectAlpha", 2.5);
130 }
131
maxMergeAlpha() const132 qreal KisImageConfig::maxMergeAlpha() const
133 {
134 return m_config.readEntry("maxMergeAlpha", 1.);
135 }
136
maxMergeCollectAlpha() const137 qreal KisImageConfig::maxMergeCollectAlpha() const
138 {
139 return m_config.readEntry("maxMergeCollectAlpha", 1.5);
140 }
141
schedulerBalancingRatio() const142 qreal KisImageConfig::schedulerBalancingRatio() const
143 {
144 /**
145 * updates-queue-size / strokes-queue-size
146 */
147 return m_config.readEntry("schedulerBalancingRatio", 100.);
148 }
149
setSchedulerBalancingRatio(qreal value)150 void KisImageConfig::setSchedulerBalancingRatio(qreal value)
151 {
152 m_config.writeEntry("schedulerBalancingRatio", value);
153 }
154
maxSwapSize(bool requestDefault) const155 int KisImageConfig::maxSwapSize(bool requestDefault) const
156 {
157 return !requestDefault ?
158 m_config.readEntry("maxSwapSize", 4096) : 4096; // in MiB
159 }
160
setMaxSwapSize(int value)161 void KisImageConfig::setMaxSwapSize(int value)
162 {
163 m_config.writeEntry("maxSwapSize", value);
164 }
165
swapSlabSize() const166 int KisImageConfig::swapSlabSize() const
167 {
168 return m_config.readEntry("swapSlabSize", 64); // in MiB
169 }
170
setSwapSlabSize(int value)171 void KisImageConfig::setSwapSlabSize(int value)
172 {
173 m_config.writeEntry("swapSlabSize", value);
174 }
175
swapWindowSize() const176 int KisImageConfig::swapWindowSize() const
177 {
178 return m_config.readEntry("swapWindowSize", 16); // in MiB
179 }
180
setSwapWindowSize(int value)181 void KisImageConfig::setSwapWindowSize(int value)
182 {
183 m_config.writeEntry("swapWindowSize", value);
184 }
185
tilesHardLimit() const186 int KisImageConfig::tilesHardLimit() const
187 {
188 qreal hp = qreal(memoryHardLimitPercent()) / 100.0;
189 qreal pp = qreal(memoryPoolLimitPercent()) / 100.0;
190
191 return totalRAM() * hp * (1 - pp);
192 }
193
tilesSoftLimit() const194 int KisImageConfig::tilesSoftLimit() const
195 {
196 qreal sp = qreal(memorySoftLimitPercent()) / 100.0;
197
198 return tilesHardLimit() * sp;
199 }
200
poolLimit() const201 int KisImageConfig::poolLimit() const
202 {
203 qreal hp = qreal(memoryHardLimitPercent()) / 100.0;
204 qreal pp = qreal(memoryPoolLimitPercent()) / 100.0;
205
206 return totalRAM() * hp * pp;
207 }
208
memoryHardLimitPercent(bool requestDefault) const209 qreal KisImageConfig::memoryHardLimitPercent(bool requestDefault) const
210 {
211 return !requestDefault ?
212 m_config.readEntry("memoryHardLimitPercent", 50.) : 50.;
213 }
214
setMemoryHardLimitPercent(qreal value)215 void KisImageConfig::setMemoryHardLimitPercent(qreal value)
216 {
217 m_config.writeEntry("memoryHardLimitPercent", value);
218 }
219
memorySoftLimitPercent(bool requestDefault) const220 qreal KisImageConfig::memorySoftLimitPercent(bool requestDefault) const
221 {
222 return !requestDefault ?
223 m_config.readEntry("memorySoftLimitPercent", 2.) : 2.;
224 }
225
setMemorySoftLimitPercent(qreal value)226 void KisImageConfig::setMemorySoftLimitPercent(qreal value)
227 {
228 m_config.writeEntry("memorySoftLimitPercent", value);
229 }
230
memoryPoolLimitPercent(bool requestDefault) const231 qreal KisImageConfig::memoryPoolLimitPercent(bool requestDefault) const
232 {
233 return !requestDefault ?
234 m_config.readEntry("memoryPoolLimitPercent", 0.0) : 0.0;
235 }
236
setMemoryPoolLimitPercent(qreal value)237 void KisImageConfig::setMemoryPoolLimitPercent(qreal value)
238 {
239 m_config.writeEntry("memoryPoolLimitPercent", value);
240 }
241
safelyGetWritableTempLocation(const QString & suffix,const QString & configKey,bool requestDefault) const242 QString KisImageConfig::safelyGetWritableTempLocation(const QString &suffix, const QString &configKey, bool requestDefault) const
243 {
244 #ifdef Q_OS_MACOS
245 // On OSX, QDir::tempPath() gives us a folder we cannot reply upon (usually
246 // something like /var/folders/.../...) and that will have vanished when we
247 // try to create the tmp file in KisMemoryWindow::KisMemoryWindow using
248 // swapFileTemplate. thus, we just pick the home folder if swapDir does not
249 // tell us otherwise.
250
251 // the other option here would be to use a "garbled name" temp file (i.e. no name
252 // KRITA_SWAP_FILE_XXXXXX) in an obscure /var/folders place, which is not
253 // nice to the user. having a clearly named swap file in the home folder is
254 // much nicer to Krita's users.
255
256 // furthermore, this is just a default and swapDir can always be configured
257 // to another location.
258
259 QString swap = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + '/' + suffix;
260 #else
261 Q_UNUSED(suffix);
262 QString swap = QDir::tempPath();
263 #endif
264 if (requestDefault) {
265 return swap;
266 }
267 const QString configuredSwap = m_config.readEntry(configKey, swap);
268 if (!configuredSwap.isEmpty()) {
269 swap = configuredSwap;
270 }
271
272 QString chosenLocation;
273 QStringList proposedSwapLocations;
274 proposedSwapLocations << swap;
275 proposedSwapLocations << QDir::tempPath();
276 proposedSwapLocations << QDir::homePath();
277
278 Q_FOREACH (const QString location, proposedSwapLocations) {
279 if (!QFileInfo(location).isWritable()) continue;
280
281 /**
282 * On NTFS, isWritable() doesn't check for attributes due to performance
283 * reasons, so we should try it in a brute-force way...
284 * (yes, there is a hacky-global-variable workaround, but let's be safe)
285 */
286 QTemporaryFile tempFile;
287 tempFile.setFileTemplate(location + '/' + "krita_test_swap_location");
288 if (tempFile.open() && !tempFile.fileName().isEmpty()) {
289 chosenLocation = location;
290 break;
291 }
292 }
293
294 if (chosenLocation.isEmpty()) {
295 qCritical() << "CRITICAL: no writable location for a swap file found! Tried the following paths:" << proposedSwapLocations;
296 qCritical() << "CRITICAL: hope I don't crash...";
297 chosenLocation = swap;
298 }
299
300 if (chosenLocation != swap) {
301 qWarning() << "WARNING: configured swap location is not writable, using a fall-back location" << swap << "->" << chosenLocation;
302 }
303
304 return chosenLocation;
305 }
306
307
swapDir(bool requestDefault)308 QString KisImageConfig::swapDir(bool requestDefault)
309 {
310 return safelyGetWritableTempLocation("swap", "swaplocation", requestDefault);
311 }
312
setSwapDir(const QString & swapDir)313 void KisImageConfig::setSwapDir(const QString &swapDir)
314 {
315 m_config.writeEntry("swaplocation", swapDir);
316 }
317
numberOfOnionSkins() const318 int KisImageConfig::numberOfOnionSkins() const
319 {
320 return m_config.readEntry("numberOfOnionSkins", 10);
321 }
322
setNumberOfOnionSkins(int value)323 void KisImageConfig::setNumberOfOnionSkins(int value)
324 {
325 m_config.writeEntry("numberOfOnionSkins", value);
326 }
327
onionSkinTintFactor() const328 int KisImageConfig::onionSkinTintFactor() const
329 {
330 return m_config.readEntry("onionSkinTintFactor", 192);
331 }
332
setOnionSkinTintFactor(int value)333 void KisImageConfig::setOnionSkinTintFactor(int value)
334 {
335 m_config.writeEntry("onionSkinTintFactor", value);
336 }
337
onionSkinOpacity(int offset) const338 int KisImageConfig::onionSkinOpacity(int offset) const
339 {
340 int value = m_config.readEntry("onionSkinOpacity_" + QString::number(offset), -1);
341
342 if (value < 0) {
343 const int num = numberOfOnionSkins();
344 const qreal dx = qreal(qAbs(offset)) / num;
345 value = 0.7 * exp(-pow2(dx) / 0.5) * 255;
346 }
347
348 return value;
349 }
350
setOnionSkinOpacity(int offset,int value)351 void KisImageConfig::setOnionSkinOpacity(int offset, int value)
352 {
353 m_config.writeEntry("onionSkinOpacity_" + QString::number(offset), value);
354 }
355
onionSkinState(int offset) const356 bool KisImageConfig::onionSkinState(int offset) const
357 {
358 bool enableByDefault = (qAbs(offset) <= 2);
359 return m_config.readEntry("onionSkinState_" + QString::number(offset), enableByDefault);
360 }
361
setOnionSkinState(int offset,bool value)362 void KisImageConfig::setOnionSkinState(int offset, bool value)
363 {
364 m_config.writeEntry("onionSkinState_" + QString::number(offset), value);
365 }
366
onionSkinTintColorBackward() const367 QColor KisImageConfig::onionSkinTintColorBackward() const
368 {
369 return m_config.readEntry("onionSkinTintColorBackward", QColor(Qt::red));
370 }
371
setOnionSkinTintColorBackward(const QColor & value)372 void KisImageConfig::setOnionSkinTintColorBackward(const QColor &value)
373 {
374 m_config.writeEntry("onionSkinTintColorBackward", value);
375 }
376
onionSkinTintColorForward() const377 QColor KisImageConfig::onionSkinTintColorForward() const
378 {
379 return m_config.readEntry("oninSkinTintColorForward", QColor(Qt::green));
380 }
381
setOnionSkinTintColorForward(const QColor & value)382 void KisImageConfig::setOnionSkinTintColorForward(const QColor &value)
383 {
384 m_config.writeEntry("oninSkinTintColorForward", value);
385 }
386
lazyFrameCreationEnabled(bool requestDefault) const387 bool KisImageConfig::lazyFrameCreationEnabled(bool requestDefault) const
388 {
389 return !requestDefault ?
390 m_config.readEntry("lazyFrameCreationEnabled", true) : true;
391 }
392
setLazyFrameCreationEnabled(bool value)393 void KisImageConfig::setLazyFrameCreationEnabled(bool value)
394 {
395 m_config.writeEntry("lazyFrameCreationEnabled", value);
396 }
397
398
399 #if defined Q_OS_LINUX
400 #include <sys/sysinfo.h>
401 #elif defined Q_OS_FREEBSD || defined Q_OS_NETBSD || defined Q_OS_OPENBSD
402 #include <sys/sysctl.h>
403 #elif defined Q_OS_WIN
404 #include <windows.h>
405 #elif defined Q_OS_MACOS
406 #include <sys/types.h>
407 #include <sys/sysctl.h>
408 #endif
409
totalRAM()410 int KisImageConfig::totalRAM()
411 {
412 // let's think that default memory size is 1000MiB
413 int totalMemory = 1000; // MiB
414 int error = 1;
415
416 #if defined Q_OS_LINUX
417 struct sysinfo info;
418
419 error = sysinfo(&info);
420 if(!error) {
421 totalMemory = info.totalram * info.mem_unit / (1UL << 20);
422 }
423 #elif defined Q_OS_FREEBSD || defined Q_OS_NETBSD || defined Q_OS_OPENBSD
424 u_long physmem;
425 # if defined HW_PHYSMEM64 // NetBSD only
426 int mib[] = {CTL_HW, HW_PHYSMEM64};
427 # else
428 int mib[] = {CTL_HW, HW_PHYSMEM};
429 # endif
430 size_t len = sizeof(physmem);
431
432 error = sysctl(mib, 2, &physmem, &len, 0, 0);
433 if(!error) {
434 totalMemory = physmem >> 20;
435 }
436 #elif defined Q_OS_WIN
437 MEMORYSTATUSEX status;
438 status.dwLength = sizeof(status);
439 error = !GlobalMemoryStatusEx(&status);
440
441 if (!error) {
442 totalMemory = status.ullTotalPhys >> 20;
443 }
444
445 // For 32 bit windows, the total memory available is at max the 2GB per process memory limit.
446 # if defined ENV32BIT
447 totalMemory = qMin(totalMemory, 2000);
448 # endif
449 #elif defined Q_OS_MACOS
450 int mib[2] = { CTL_HW, HW_MEMSIZE };
451 u_int namelen = sizeof(mib) / sizeof(mib[0]);
452 uint64_t size;
453 size_t len = sizeof(size);
454
455 errno = 0;
456 if (sysctl(mib, namelen, &size, &len, 0, 0) >= 0) {
457 totalMemory = size >> 20;
458 error = 0;
459 }
460 else {
461 dbgKrita << "sysctl(\"hw.memsize\") raised error" << strerror(errno);
462 }
463 #endif
464
465 if (error) {
466 warnKrita << "Cannot get the size of your RAM. Using 1 GiB by default.";
467 }
468
469 return totalMemory;
470 }
471
showAdditionalOnionSkinsSettings(bool requestDefault) const472 bool KisImageConfig::showAdditionalOnionSkinsSettings(bool requestDefault) const
473 {
474 return !requestDefault ?
475 m_config.readEntry("showAdditionalOnionSkinsSettings", true) : true;
476 }
477
setShowAdditionalOnionSkinsSettings(bool value)478 void KisImageConfig::setShowAdditionalOnionSkinsSettings(bool value)
479 {
480 m_config.writeEntry("showAdditionalOnionSkinsSettings", value);
481 }
482
defaultFrameColorLabel() const483 int KisImageConfig::defaultFrameColorLabel() const
484 {
485 return m_config.readEntry("defaultFrameColorLabel", 0);
486 }
487
setDefaultFrameColorLabel(int label)488 void KisImageConfig::setDefaultFrameColorLabel(int label)
489 {
490 m_config.writeEntry("defaultFrameColorLabel", label);
491 }
492
defaultProofingconfiguration()493 KisProofingConfigurationSP KisImageConfig::defaultProofingconfiguration()
494 {
495 KisProofingConfiguration *proofingConfig= new KisProofingConfiguration();
496 proofingConfig->proofingProfile = m_config.readEntry("defaultProofingProfileName", "Chemical proof");
497 proofingConfig->proofingModel = m_config.readEntry("defaultProofingProfileModel", "CMYKA");
498 proofingConfig->proofingDepth = m_config.readEntry("defaultProofingProfileDepth", "U8");
499 proofingConfig->intent = (KoColorConversionTransformation::Intent)m_config.readEntry("defaultProofingProfileIntent", 3);
500 if (m_config.readEntry("defaultProofingBlackpointCompensation", true)) {
501 proofingConfig->conversionFlags |= KoColorConversionTransformation::ConversionFlag::BlackpointCompensation;
502 } else {
503 proofingConfig->conversionFlags = proofingConfig->conversionFlags & ~KoColorConversionTransformation::ConversionFlag::BlackpointCompensation;
504 }
505 QColor def(Qt::green);
506 m_config.readEntry("defaultProofingGamutwarning", def);
507 KoColor col(KoColorSpaceRegistry::instance()->rgb8());
508 col.fromQColor(def);
509 col.setOpacity(1.0);
510 proofingConfig->warningColor = col;
511 proofingConfig->adaptationState = (double)m_config.readEntry("defaultProofingAdaptationState", 1.0);
512 return toQShared(proofingConfig);
513 }
514
setDefaultProofingConfig(const KoColorSpace * proofingSpace,int proofingIntent,bool blackPointCompensation,KoColor warningColor,double adaptationState)515 void KisImageConfig::setDefaultProofingConfig(const KoColorSpace *proofingSpace, int proofingIntent, bool blackPointCompensation, KoColor warningColor, double adaptationState)
516 {
517 m_config.writeEntry("defaultProofingProfileName", proofingSpace->profile()->name());
518 m_config.writeEntry("defaultProofingProfileModel", proofingSpace->colorModelId().id());
519 m_config.writeEntry("defaultProofingProfileDepth", proofingSpace->colorDepthId().id());
520 m_config.writeEntry("defaultProofingProfileIntent", proofingIntent);
521 m_config.writeEntry("defaultProofingBlackpointCompensation", blackPointCompensation);
522 QColor c;
523 c = warningColor.toQColor();
524 m_config.writeEntry("defaultProofingGamutwarning", c);
525 m_config.writeEntry("defaultProofingAdaptationState",adaptationState);
526 }
527
useLodForColorizeMask(bool requestDefault) const528 bool KisImageConfig::useLodForColorizeMask(bool requestDefault) const
529 {
530 return !requestDefault ?
531 m_config.readEntry("useLodForColorizeMask", false) : false;
532 }
533
setUseLodForColorizeMask(bool value)534 void KisImageConfig::setUseLodForColorizeMask(bool value)
535 {
536 m_config.writeEntry("useLodForColorizeMask", value);
537 }
538
maxNumberOfThreads(bool defaultValue) const539 int KisImageConfig::maxNumberOfThreads(bool defaultValue) const
540 {
541 return (defaultValue ? QThread::idealThreadCount() : m_config.readEntry("maxNumberOfThreads", QThread::idealThreadCount()));
542 }
543
setMaxNumberOfThreads(int value)544 void KisImageConfig::setMaxNumberOfThreads(int value)
545 {
546 if (value == QThread::idealThreadCount()) {
547 m_config.deleteEntry("maxNumberOfThreads");
548 } else {
549 m_config.writeEntry("maxNumberOfThreads", value);
550 }
551 }
552
frameRenderingClones(bool defaultValue) const553 int KisImageConfig::frameRenderingClones(bool defaultValue) const
554 {
555 const int defaultClonesCount = qMax(1, maxNumberOfThreads(defaultValue) / 2);
556 return defaultValue ? defaultClonesCount : m_config.readEntry("frameRenderingClones", defaultClonesCount);
557 }
558
setFrameRenderingClones(int value)559 void KisImageConfig::setFrameRenderingClones(int value)
560 {
561 m_config.writeEntry("frameRenderingClones", value);
562 }
563
fpsLimit(bool defaultValue) const564 int KisImageConfig::fpsLimit(bool defaultValue) const
565 {
566 int limit = defaultValue ? 100 : m_config.readEntry("fpsLimit", 100);
567 return limit > 0 ? limit : 1;
568 }
569
setFpsLimit(int value)570 void KisImageConfig::setFpsLimit(int value)
571 {
572 m_config.writeEntry("fpsLimit", value);
573 }
574
useOnDiskAnimationCacheSwapping(bool defaultValue) const575 bool KisImageConfig::useOnDiskAnimationCacheSwapping(bool defaultValue) const
576 {
577 return defaultValue ? true : m_config.readEntry("useOnDiskAnimationCacheSwapping", true);
578 }
579
setUseOnDiskAnimationCacheSwapping(bool value)580 void KisImageConfig::setUseOnDiskAnimationCacheSwapping(bool value)
581 {
582 m_config.writeEntry("useOnDiskAnimationCacheSwapping", value);
583 }
584
animationCacheDir(bool defaultValue) const585 QString KisImageConfig::animationCacheDir(bool defaultValue) const
586 {
587 return safelyGetWritableTempLocation("animation_cache", "animationCacheDir", defaultValue);
588 }
589
setAnimationCacheDir(const QString & value)590 void KisImageConfig::setAnimationCacheDir(const QString &value)
591 {
592 m_config.writeEntry("animationCacheDir", value);
593 }
594
useAnimationCacheFrameSizeLimit(bool defaultValue) const595 bool KisImageConfig::useAnimationCacheFrameSizeLimit(bool defaultValue) const
596 {
597 return defaultValue ? true : m_config.readEntry("useAnimationCacheFrameSizeLimit", true);
598 }
599
setUseAnimationCacheFrameSizeLimit(bool value)600 void KisImageConfig::setUseAnimationCacheFrameSizeLimit(bool value)
601 {
602 m_config.writeEntry("useAnimationCacheFrameSizeLimit", value);
603 }
604
animationCacheFrameSizeLimit(bool defaultValue) const605 int KisImageConfig::animationCacheFrameSizeLimit(bool defaultValue) const
606 {
607 return defaultValue ? 2500 : m_config.readEntry("animationCacheFrameSizeLimit", 2500);
608 }
609
setAnimationCacheFrameSizeLimit(int value)610 void KisImageConfig::setAnimationCacheFrameSizeLimit(int value)
611 {
612 m_config.writeEntry("animationCacheFrameSizeLimit", value);
613 }
614
useAnimationCacheRegionOfInterest(bool defaultValue) const615 bool KisImageConfig::useAnimationCacheRegionOfInterest(bool defaultValue) const
616 {
617 return defaultValue ? true : m_config.readEntry("useAnimationCacheRegionOfInterest", true);
618 }
619
setUseAnimationCacheRegionOfInterest(bool value)620 void KisImageConfig::setUseAnimationCacheRegionOfInterest(bool value)
621 {
622 m_config.writeEntry("useAnimationCacheRegionOfInterest", value);
623 }
624
animationCacheRegionOfInterestMargin(bool defaultValue) const625 qreal KisImageConfig::animationCacheRegionOfInterestMargin(bool defaultValue) const
626 {
627 return defaultValue ? 0.25 : m_config.readEntry("animationCacheRegionOfInterestMargin", 0.25);
628 }
629
setAnimationCacheRegionOfInterestMargin(qreal value)630 void KisImageConfig::setAnimationCacheRegionOfInterestMargin(qreal value)
631 {
632 m_config.writeEntry("animationCacheRegionOfInterestMargin", value);
633 }
634
selectionOverlayMaskColor(bool defaultValue) const635 QColor KisImageConfig::selectionOverlayMaskColor(bool defaultValue) const
636 {
637 QColor def(255, 0, 0, 128);
638 return (defaultValue ? def : m_config.readEntry("selectionOverlayMaskColor", def));
639 }
640
setSelectionOverlayMaskColor(const QColor & color)641 void KisImageConfig::setSelectionOverlayMaskColor(const QColor &color)
642 {
643 m_config.writeEntry("selectionOverlayMaskColor", color);
644 }
645
resetConfig()646 void KisImageConfig::resetConfig()
647 {
648 KConfigGroup config = KSharedConfig::openConfig()->group(QString());
649 config.deleteGroup();
650 }
651