File indexing completed on 2024-05-19 04:26:17
0001 /* 0002 * SPDX-FileCopyrightText: 2010 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_image_config.h" 0008 0009 #include <ksharedconfig.h> 0010 0011 #include <KoConfig.h> 0012 #include <KoColorProfile.h> 0013 #include <KoColorSpaceRegistry.h> 0014 #include <KoColorConversionTransformation.h> 0015 #include <kis_properties_configuration.h> 0016 0017 #include "kis_debug.h" 0018 0019 #include <QThread> 0020 #include <QApplication> 0021 #include <QColor> 0022 #include <QDir> 0023 0024 #include "kis_global.h" 0025 #include <cmath> 0026 #include <QTemporaryFile> 0027 0028 #ifdef Q_OS_MACOS 0029 #include <errno.h> 0030 #include "KisMacosSecurityBookmarkManager.h" 0031 #endif 0032 0033 KisImageConfig::KisImageConfig(bool readOnly) 0034 : m_config(KSharedConfig::openConfig()->group(QString())) 0035 , m_readOnly(readOnly) 0036 { 0037 if (!readOnly) { 0038 KIS_SAFE_ASSERT_RECOVER_RETURN(qApp->thread() == QThread::currentThread()); 0039 } 0040 #ifdef Q_OS_MACOS 0041 // clear /var/folders/ swap path set by old broken Krita swap implementation in order to use new default swap dir. 0042 QString swap = m_config.readEntry("swaplocation", ""); 0043 if (swap.startsWith("/var/folders/")) { 0044 m_config.deleteEntry("swaplocation"); 0045 } 0046 #endif 0047 } 0048 0049 KisImageConfig::~KisImageConfig() 0050 { 0051 if (m_readOnly) return; 0052 0053 if (qApp->thread() != QThread::currentThread()) { 0054 dbgKrita << "KisImageConfig: requested config synchronization from nonGUI thread! Called from" << kisBacktrace(); 0055 return; 0056 } 0057 0058 m_config.sync(); 0059 } 0060 0061 bool KisImageConfig::enableProgressReporting(bool requestDefault) const 0062 { 0063 return !requestDefault ? 0064 m_config.readEntry("enableProgressReporting", true) : true; 0065 } 0066 0067 void KisImageConfig::setEnableProgressReporting(bool value) 0068 { 0069 m_config.writeEntry("enableProgressReporting", value); 0070 } 0071 0072 bool KisImageConfig::enablePerfLog(bool requestDefault) const 0073 { 0074 return !requestDefault ? 0075 m_config.readEntry("enablePerfLog", false) :false; 0076 } 0077 0078 void KisImageConfig::setEnablePerfLog(bool value) 0079 { 0080 m_config.writeEntry("enablePerfLog", value); 0081 } 0082 0083 qreal KisImageConfig::transformMaskOffBoundsReadArea() const 0084 { 0085 return m_config.readEntry("transformMaskOffBoundsReadArea", 0.5); 0086 } 0087 0088 int KisImageConfig::updatePatchHeight() const 0089 { 0090 int patchHeight = m_config.readEntry("updatePatchHeight", 512); 0091 if (patchHeight <= 0) return 512; 0092 return patchHeight; 0093 } 0094 0095 void KisImageConfig::setUpdatePatchHeight(int value) 0096 { 0097 m_config.writeEntry("updatePatchHeight", value); 0098 } 0099 0100 int KisImageConfig::updatePatchWidth() const 0101 { 0102 int patchWidth = m_config.readEntry("updatePatchWidth", 512); 0103 if (patchWidth <= 0) return 512; 0104 return patchWidth; 0105 } 0106 0107 void KisImageConfig::setUpdatePatchWidth(int value) 0108 { 0109 m_config.writeEntry("updatePatchWidth", value); 0110 } 0111 0112 qreal KisImageConfig::maxCollectAlpha() const 0113 { 0114 return m_config.readEntry("maxCollectAlpha", 2.5); 0115 } 0116 0117 qreal KisImageConfig::maxMergeAlpha() const 0118 { 0119 return m_config.readEntry("maxMergeAlpha", 1.); 0120 } 0121 0122 qreal KisImageConfig::maxMergeCollectAlpha() const 0123 { 0124 return m_config.readEntry("maxMergeCollectAlpha", 1.5); 0125 } 0126 0127 qreal KisImageConfig::schedulerBalancingRatio() const 0128 { 0129 /** 0130 * updates-queue-size / strokes-queue-size 0131 */ 0132 return m_config.readEntry("schedulerBalancingRatio", 100.); 0133 } 0134 0135 void KisImageConfig::setSchedulerBalancingRatio(qreal value) 0136 { 0137 m_config.writeEntry("schedulerBalancingRatio", value); 0138 } 0139 0140 int KisImageConfig::maxSwapSize(bool requestDefault) const 0141 { 0142 return !requestDefault ? 0143 m_config.readEntry("maxSwapSize", 4096) : 4096; // in MiB 0144 } 0145 0146 void KisImageConfig::setMaxSwapSize(int value) 0147 { 0148 m_config.writeEntry("maxSwapSize", value); 0149 } 0150 0151 int KisImageConfig::swapSlabSize() const 0152 { 0153 return m_config.readEntry("swapSlabSize", 64); // in MiB 0154 } 0155 0156 void KisImageConfig::setSwapSlabSize(int value) 0157 { 0158 m_config.writeEntry("swapSlabSize", value); 0159 } 0160 0161 int KisImageConfig::swapWindowSize() const 0162 { 0163 return m_config.readEntry("swapWindowSize", 16); // in MiB 0164 } 0165 0166 void KisImageConfig::setSwapWindowSize(int value) 0167 { 0168 m_config.writeEntry("swapWindowSize", value); 0169 } 0170 0171 int KisImageConfig::tilesHardLimit() const 0172 { 0173 qreal hp = qreal(memoryHardLimitPercent()) / 100.0; 0174 qreal pp = qreal(memoryPoolLimitPercent()) / 100.0; 0175 0176 return totalRAM() * hp * (1 - pp); 0177 } 0178 0179 int KisImageConfig::tilesSoftLimit() const 0180 { 0181 qreal sp = qreal(memorySoftLimitPercent()) / 100.0; 0182 0183 return tilesHardLimit() * sp; 0184 } 0185 0186 int KisImageConfig::poolLimit() const 0187 { 0188 qreal hp = qreal(memoryHardLimitPercent()) / 100.0; 0189 qreal pp = qreal(memoryPoolLimitPercent()) / 100.0; 0190 0191 return totalRAM() * hp * pp; 0192 } 0193 0194 qreal KisImageConfig::memoryHardLimitPercent(bool requestDefault) const 0195 { 0196 return !requestDefault ? 0197 m_config.readEntry("memoryHardLimitPercent", 50.) : 50.; 0198 } 0199 0200 void KisImageConfig::setMemoryHardLimitPercent(qreal value) 0201 { 0202 m_config.writeEntry("memoryHardLimitPercent", value); 0203 } 0204 0205 qreal KisImageConfig::memorySoftLimitPercent(bool requestDefault) const 0206 { 0207 return !requestDefault ? 0208 m_config.readEntry("memorySoftLimitPercent", 2.) : 2.; 0209 } 0210 0211 void KisImageConfig::setMemorySoftLimitPercent(qreal value) 0212 { 0213 m_config.writeEntry("memorySoftLimitPercent", value); 0214 } 0215 0216 qreal KisImageConfig::memoryPoolLimitPercent(bool requestDefault) const 0217 { 0218 return !requestDefault ? 0219 m_config.readEntry("memoryPoolLimitPercent", 0.0) : 0.0; 0220 } 0221 0222 void KisImageConfig::setMemoryPoolLimitPercent(qreal value) 0223 { 0224 m_config.writeEntry("memoryPoolLimitPercent", value); 0225 } 0226 0227 QString KisImageConfig::safelyGetWritableTempLocation(const QString &suffix, const QString &configKey, bool requestDefault) const 0228 { 0229 #ifdef Q_OS_MACOS 0230 // On OSX, QDir::tempPath() gives us a folder we cannot reply upon (usually 0231 // something like /var/folders/.../...) and that will have vanished when we 0232 // try to create the tmp file in KisMemoryWindow::KisMemoryWindow using 0233 // swapFileTemplate. thus, we just pick the home folder if swapDir does not 0234 // tell us otherwise. 0235 0236 // the other option here would be to use a "garbled name" temp file (i.e. no name 0237 // KRITA_SWAP_FILE_XXXXXX) in an obscure /var/folders place, which is not 0238 // nice to the user. having a clearly named swap file in the home folder is 0239 // much nicer to Krita's users. 0240 0241 // NOTE: QStandardPaths::AppLocalDataLocation on macos sandboxed envs 0242 // does not return writable locations at all times, using QDir static methods 0243 // will always return locations inside the sandbox Container 0244 0245 // furthermore, this is just a default and swapDir can always be configured 0246 // to another location. 0247 0248 QString swap; 0249 0250 KisMacosSecurityBookmarkManager *bookmarkmngr = KisMacosSecurityBookmarkManager::instance(); 0251 if ( bookmarkmngr->isSandboxed() ) { 0252 QDir sandboxHome = QDir::home(); 0253 if (sandboxHome.cd("tmp")) { 0254 swap = sandboxHome.path(); 0255 } 0256 } else { 0257 swap = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + '/' + suffix; 0258 } 0259 #else 0260 Q_UNUSED(suffix); 0261 QString swap = QDir::tempPath(); 0262 #endif 0263 if (requestDefault) { 0264 return swap; 0265 } 0266 const QString configuredSwap = m_config.readEntry(configKey, swap); 0267 if (!configuredSwap.isEmpty()) { 0268 swap = configuredSwap; 0269 } 0270 0271 QString chosenLocation; 0272 QStringList proposedSwapLocations; 0273 0274 proposedSwapLocations << swap; 0275 proposedSwapLocations << QDir::tempPath(); 0276 proposedSwapLocations << QDir::homePath(); 0277 0278 Q_FOREACH (const QString location, proposedSwapLocations) { 0279 if (!QFileInfo(location).isWritable()) continue; 0280 0281 /** 0282 * On NTFS, isWritable() doesn't check for attributes due to performance 0283 * reasons, so we should try it in a brute-force way... 0284 * (yes, there is a hacky-global-variable workaround, but let's be safe) 0285 */ 0286 QTemporaryFile tempFile; 0287 tempFile.setFileTemplate(location + '/' + "krita_test_swap_location"); 0288 if (tempFile.open() && !tempFile.fileName().isEmpty()) { 0289 chosenLocation = location; 0290 break; 0291 } 0292 } 0293 0294 if (chosenLocation.isEmpty()) { 0295 qCritical() << "CRITICAL: no writable location for a swap file found! Tried the following paths:" << proposedSwapLocations; 0296 qCritical() << "CRITICAL: hope I don't crash..."; 0297 chosenLocation = swap; 0298 } 0299 0300 if (chosenLocation != swap) { 0301 qWarning() << "WARNING: configured swap location is not writable, using a fall-back location" << swap << "->" << chosenLocation; 0302 } 0303 0304 return chosenLocation; 0305 } 0306 0307 0308 QString KisImageConfig::swapDir(bool requestDefault) 0309 { 0310 return safelyGetWritableTempLocation("swap", "swaplocation", requestDefault); 0311 } 0312 0313 void KisImageConfig::setSwapDir(const QString &swapDir) 0314 { 0315 m_config.writeEntry("swaplocation", swapDir); 0316 } 0317 0318 int KisImageConfig::numberOfOnionSkins() const 0319 { 0320 return m_config.readEntry("numberOfOnionSkins", 10); 0321 } 0322 0323 void KisImageConfig::setNumberOfOnionSkins(int value) 0324 { 0325 m_config.writeEntry("numberOfOnionSkins", value); 0326 } 0327 0328 int KisImageConfig::onionSkinTintFactor() const 0329 { 0330 return m_config.readEntry("onionSkinTintFactor", 192); 0331 } 0332 0333 void KisImageConfig::setOnionSkinTintFactor(int value) 0334 { 0335 m_config.writeEntry("onionSkinTintFactor", value); 0336 } 0337 0338 int KisImageConfig::onionSkinOpacity(int offset) const 0339 { 0340 int value = m_config.readEntry("onionSkinOpacity_" + QString::number(offset), -1); 0341 0342 return value; 0343 } 0344 0345 void KisImageConfig::setOnionSkinOpacity(int offset, int value) 0346 { 0347 m_config.writeEntry("onionSkinOpacity_" + QString::number(offset), value); 0348 } 0349 0350 bool KisImageConfig::onionSkinState(int offset) const 0351 { 0352 bool enableByDefault = (qAbs(offset) <= 2); 0353 return m_config.readEntry("onionSkinState_" + QString::number(offset), enableByDefault); 0354 } 0355 0356 void KisImageConfig::setOnionSkinState(int offset, bool value) 0357 { 0358 m_config.writeEntry("onionSkinState_" + QString::number(offset), value); 0359 } 0360 0361 QColor KisImageConfig::onionSkinTintColorBackward() const 0362 { 0363 return m_config.readEntry("onionSkinTintColorBackward", QColor(Qt::red)); 0364 } 0365 0366 void KisImageConfig::setOnionSkinTintColorBackward(const QColor &value) 0367 { 0368 m_config.writeEntry("onionSkinTintColorBackward", value); 0369 } 0370 0371 QColor KisImageConfig::onionSkinTintColorForward() const 0372 { 0373 return m_config.readEntry("oninSkinTintColorForward", QColor(Qt::green)); 0374 } 0375 0376 void KisImageConfig::setOnionSkinTintColorForward(const QColor &value) 0377 { 0378 m_config.writeEntry("oninSkinTintColorForward", value); 0379 } 0380 0381 bool KisImageConfig::autoKeyEnabled(bool requestDefault) const 0382 { 0383 return !requestDefault ? 0384 m_config.readEntry("lazyFrameCreationEnabled", true) : true; 0385 } 0386 0387 void KisImageConfig::setAutoKeyEnabled(bool value) 0388 { 0389 m_config.writeEntry("lazyFrameCreationEnabled", value); 0390 } 0391 0392 bool KisImageConfig::autoKeyModeDuplicate(bool requestDefault) const 0393 { 0394 return !requestDefault ? 0395 m_config.readEntry("lazyFrameModeDuplicate", true) : true; 0396 } 0397 0398 void KisImageConfig::setAutoKeyModeDuplicate(bool value) 0399 { 0400 m_config.writeEntry("lazyFrameModeDuplicate", value); 0401 } 0402 0403 #if defined Q_OS_LINUX 0404 #include <sys/sysinfo.h> 0405 #elif defined Q_OS_FREEBSD || defined Q_OS_NETBSD || defined Q_OS_OPENBSD 0406 #include <sys/sysctl.h> 0407 #elif defined Q_OS_WIN 0408 #include <windows.h> 0409 #elif defined Q_OS_MACOS 0410 #include <sys/types.h> 0411 #include <sys/sysctl.h> 0412 #endif 0413 0414 int KisImageConfig::totalRAM() 0415 { 0416 // let's think that default memory size is 1000MiB 0417 int totalMemory = 1000; // MiB 0418 int error = 1; 0419 0420 #if defined Q_OS_LINUX 0421 struct sysinfo info; 0422 0423 error = sysinfo(&info); 0424 if(!error) { 0425 totalMemory = info.totalram * info.mem_unit / (1UL << 20); 0426 } 0427 #elif defined Q_OS_FREEBSD || defined Q_OS_NETBSD || defined Q_OS_OPENBSD 0428 u_long physmem; 0429 # if defined HW_PHYSMEM64 // NetBSD only 0430 int mib[] = {CTL_HW, HW_PHYSMEM64}; 0431 # else 0432 int mib[] = {CTL_HW, HW_PHYSMEM}; 0433 # endif 0434 size_t len = sizeof(physmem); 0435 0436 error = sysctl(mib, 2, &physmem, &len, 0, 0); 0437 if(!error) { 0438 totalMemory = physmem >> 20; 0439 } 0440 #elif defined Q_OS_WIN 0441 MEMORYSTATUSEX status; 0442 status.dwLength = sizeof(status); 0443 error = !GlobalMemoryStatusEx(&status); 0444 0445 if (!error) { 0446 totalMemory = status.ullTotalPhys >> 20; 0447 } 0448 0449 // For 32 bit windows, the total memory available is at max the 2GB per process memory limit. 0450 # if defined ENV32BIT 0451 totalMemory = qMin(totalMemory, 2000); 0452 # endif 0453 #elif defined Q_OS_MACOS 0454 int mib[2] = { CTL_HW, HW_MEMSIZE }; 0455 u_int namelen = sizeof(mib) / sizeof(mib[0]); 0456 uint64_t size; 0457 size_t len = sizeof(size); 0458 0459 errno = 0; 0460 if (sysctl(mib, namelen, &size, &len, 0, 0) >= 0) { 0461 totalMemory = size >> 20; 0462 error = 0; 0463 } 0464 else { 0465 dbgKrita << "sysctl(\"hw.memsize\") raised error" << strerror(errno); 0466 } 0467 #endif 0468 0469 if (error) { 0470 warnKrita << "Cannot get the size of your RAM. Using 1 GiB by default."; 0471 } 0472 0473 return totalMemory; 0474 } 0475 0476 bool KisImageConfig::showAdditionalOnionSkinsSettings(bool requestDefault) const 0477 { 0478 return !requestDefault ? 0479 m_config.readEntry("showAdditionalOnionSkinsSettings", true) : true; 0480 } 0481 0482 void KisImageConfig::setShowAdditionalOnionSkinsSettings(bool value) 0483 { 0484 m_config.writeEntry("showAdditionalOnionSkinsSettings", value); 0485 } 0486 0487 int KisImageConfig::defaultFrameColorLabel() const 0488 { 0489 return m_config.readEntry("defaultFrameColorLabel", 0); 0490 } 0491 0492 void KisImageConfig::setDefaultFrameColorLabel(int label) 0493 { 0494 m_config.writeEntry("defaultFrameColorLabel", label); 0495 } 0496 0497 KisProofingConfigurationSP KisImageConfig::defaultProofingconfiguration() 0498 { 0499 KisProofingConfiguration *proofingConfig= new KisProofingConfiguration(); 0500 proofingConfig->proofingProfile = m_config.readEntry("defaultProofingProfileName", "Chemical proof"); 0501 proofingConfig->proofingModel = m_config.readEntry("defaultProofingProfileModel", "CMYKA"); 0502 proofingConfig->proofingDepth = m_config.readEntry("defaultProofingProfileDepth", "U8"); 0503 proofingConfig->intent = (KoColorConversionTransformation::Intent)m_config.readEntry("defaultProofingProfileIntent", 3); 0504 if (m_config.readEntry("defaultProofingBlackpointCompensation", true)) { 0505 proofingConfig->conversionFlags |= KoColorConversionTransformation::ConversionFlag::BlackpointCompensation; 0506 } else { 0507 proofingConfig->conversionFlags = proofingConfig->conversionFlags & ~KoColorConversionTransformation::ConversionFlag::BlackpointCompensation; 0508 } 0509 QColor def(Qt::green); 0510 m_config.readEntry("defaultProofingGamutwarning", def); 0511 KoColor col(KoColorSpaceRegistry::instance()->rgb8()); 0512 col.fromQColor(def); 0513 col.setOpacity(1.0); 0514 proofingConfig->warningColor = col; 0515 proofingConfig->adaptationState = (double)m_config.readEntry("defaultProofingAdaptationState", 1.0); 0516 return toQShared(proofingConfig); 0517 } 0518 0519 void KisImageConfig::setDefaultProofingConfig(const KoColorSpace *proofingSpace, int proofingIntent, bool blackPointCompensation, KoColor warningColor, double adaptationState) 0520 { 0521 if (!proofingSpace || !proofingSpace->profile()) { 0522 return; 0523 } 0524 0525 m_config.writeEntry("defaultProofingProfileName", proofingSpace->profile()->name()); 0526 m_config.writeEntry("defaultProofingProfileModel", proofingSpace->colorModelId().id()); 0527 m_config.writeEntry("defaultProofingProfileDepth", proofingSpace->colorDepthId().id()); 0528 m_config.writeEntry("defaultProofingProfileIntent", proofingIntent); 0529 m_config.writeEntry("defaultProofingBlackpointCompensation", blackPointCompensation); 0530 QColor c; 0531 c = warningColor.toQColor(); 0532 m_config.writeEntry("defaultProofingGamutwarning", c); 0533 m_config.writeEntry("defaultProofingAdaptationState",adaptationState); 0534 } 0535 0536 bool KisImageConfig::useLodForColorizeMask(bool requestDefault) const 0537 { 0538 return !requestDefault ? 0539 m_config.readEntry("useLodForColorizeMask", false) : false; 0540 } 0541 0542 void KisImageConfig::setUseLodForColorizeMask(bool value) 0543 { 0544 m_config.writeEntry("useLodForColorizeMask", value); 0545 } 0546 0547 int KisImageConfig::maxNumberOfThreads(bool defaultValue) const 0548 { 0549 return (defaultValue ? QThread::idealThreadCount() : m_config.readEntry("maxNumberOfThreads", QThread::idealThreadCount())); 0550 } 0551 0552 void KisImageConfig::setMaxNumberOfThreads(int value) 0553 { 0554 if (value == QThread::idealThreadCount()) { 0555 m_config.deleteEntry("maxNumberOfThreads"); 0556 } else { 0557 m_config.writeEntry("maxNumberOfThreads", value); 0558 } 0559 } 0560 0561 int KisImageConfig::frameRenderingClones(bool defaultValue) const 0562 { 0563 const int defaultClonesCount = qMax(1, maxNumberOfThreads(defaultValue) / 2); 0564 return defaultValue ? defaultClonesCount : m_config.readEntry("frameRenderingClones", defaultClonesCount); 0565 } 0566 0567 void KisImageConfig::setFrameRenderingClones(int value) 0568 { 0569 m_config.writeEntry("frameRenderingClones", value); 0570 } 0571 0572 int KisImageConfig::frameRenderingTimeout(bool defaultValue) const 0573 { 0574 const int defaultFrameRenderingTimeout = 30000; // 30 ms 0575 return defaultValue ? defaultFrameRenderingTimeout : m_config.readEntry("frameRenderingTimeout", defaultFrameRenderingTimeout); 0576 } 0577 0578 void KisImageConfig::setFrameRenderingTimeout(int value) 0579 { 0580 m_config.writeEntry("frameRenderingTimeout", value); 0581 } 0582 0583 int KisImageConfig::fpsLimit(bool defaultValue) const 0584 { 0585 int limit = defaultValue ? 100 : m_config.readEntry("fpsLimit", 100); 0586 return limit > 0 ? limit : 1; 0587 } 0588 0589 void KisImageConfig::setFpsLimit(int value) 0590 { 0591 m_config.writeEntry("fpsLimit", value); 0592 } 0593 0594 bool KisImageConfig::useOnDiskAnimationCacheSwapping(bool defaultValue) const 0595 { 0596 return defaultValue ? true : m_config.readEntry("useOnDiskAnimationCacheSwapping", true); 0597 } 0598 0599 void KisImageConfig::setUseOnDiskAnimationCacheSwapping(bool value) 0600 { 0601 m_config.writeEntry("useOnDiskAnimationCacheSwapping", value); 0602 } 0603 0604 QString KisImageConfig::animationCacheDir(bool defaultValue) const 0605 { 0606 return safelyGetWritableTempLocation("animation_cache", "animationCacheDir", defaultValue); 0607 } 0608 0609 void KisImageConfig::setAnimationCacheDir(const QString &value) 0610 { 0611 m_config.writeEntry("animationCacheDir", value); 0612 } 0613 0614 bool KisImageConfig::useAnimationCacheFrameSizeLimit(bool defaultValue) const 0615 { 0616 return defaultValue ? true : m_config.readEntry("useAnimationCacheFrameSizeLimit", true); 0617 } 0618 0619 void KisImageConfig::setUseAnimationCacheFrameSizeLimit(bool value) 0620 { 0621 m_config.writeEntry("useAnimationCacheFrameSizeLimit", value); 0622 } 0623 0624 int KisImageConfig::animationCacheFrameSizeLimit(bool defaultValue) const 0625 { 0626 return defaultValue ? 2500 : m_config.readEntry("animationCacheFrameSizeLimit", 2500); 0627 } 0628 0629 void KisImageConfig::setAnimationCacheFrameSizeLimit(int value) 0630 { 0631 m_config.writeEntry("animationCacheFrameSizeLimit", value); 0632 } 0633 0634 bool KisImageConfig::useAnimationCacheRegionOfInterest(bool defaultValue) const 0635 { 0636 return defaultValue ? true : m_config.readEntry("useAnimationCacheRegionOfInterest", true); 0637 } 0638 0639 void KisImageConfig::setUseAnimationCacheRegionOfInterest(bool value) 0640 { 0641 m_config.writeEntry("useAnimationCacheRegionOfInterest", value); 0642 } 0643 0644 qreal KisImageConfig::animationCacheRegionOfInterestMargin(bool defaultValue) const 0645 { 0646 return defaultValue ? 0.25 : m_config.readEntry("animationCacheRegionOfInterestMargin", 0.25); 0647 } 0648 0649 void KisImageConfig::setAnimationCacheRegionOfInterestMargin(qreal value) 0650 { 0651 m_config.writeEntry("animationCacheRegionOfInterestMargin", value); 0652 } 0653 0654 qreal KisImageConfig::selectionOutlineOpacity(bool defaultValue) const 0655 { 0656 return defaultValue ? 1.0 : m_config.readEntry("selectionOutlineOpacity", 1.0); 0657 } 0658 0659 void KisImageConfig::setSelectionOutlineOpacity(qreal value) 0660 { 0661 m_config.writeEntry("selectionOutlineOpacity", value); 0662 } 0663 0664 QColor KisImageConfig::selectionOverlayMaskColor(bool defaultValue) const 0665 { 0666 QColor def(255, 0, 0, 128); 0667 return (defaultValue ? def : m_config.readEntry("selectionOverlayMaskColor", def)); 0668 } 0669 0670 void KisImageConfig::setSelectionOverlayMaskColor(const QColor &color) 0671 { 0672 m_config.writeEntry("selectionOverlayMaskColor", color); 0673 } 0674 0675 int KisImageConfig::maxBrushSize(bool defaultValue) const 0676 { 0677 return !defaultValue ? m_config.readEntry("maximumBrushSize", 1000) : 1000; 0678 } 0679 0680 void KisImageConfig::setMaxBrushSize(int value) 0681 { 0682 m_config.writeEntry("maximumBrushSize", value); 0683 } 0684 0685 int KisImageConfig::maxMaskingBrushSize() const 0686 { 0687 return qMin(15000, 3 * maxBrushSize()); 0688 } 0689 0690 bool KisImageConfig::renameMergedLayers(bool defaultValue) const 0691 { 0692 return defaultValue ? true : m_config.readEntry("renameMergedLayers", true); 0693 } 0694 0695 void KisImageConfig::setRenameMergedLayers(bool value) 0696 { 0697 m_config.writeEntry("renameMergedLayers", value); 0698 } 0699 0700 QString KisImageConfig::exportConfigurationXML(const QString &exportConfigId, bool defaultValue) const 0701 { 0702 return (defaultValue ? QString() : m_config.readEntry("ExportConfiguration-" + exportConfigId, QString())); 0703 } 0704 0705 bool KisImageConfig::hasExportConfiguration(const QString &exportConfigID) 0706 { 0707 return m_config.hasKey("ExportConfiguration-" + exportConfigID); 0708 } 0709 0710 KisPropertiesConfigurationSP KisImageConfig::exportConfiguration(const QString &exportConfigId, bool defaultValue) const 0711 { 0712 KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); 0713 const QString xmlData = exportConfigurationXML(exportConfigId, defaultValue); 0714 cfg->fromXML(xmlData); 0715 return cfg; 0716 } 0717 0718 void KisImageConfig::setExportConfiguration(const QString &exportConfigId, KisPropertiesConfigurationSP properties) 0719 { 0720 const QString exportConfig = properties->toXML(); 0721 QString configId = "ExportConfiguration-" + exportConfigId; 0722 m_config.writeEntry(configId, exportConfig); 0723 } 0724 0725 void KisImageConfig::resetConfig() 0726 { 0727 KConfigGroup config = KSharedConfig::openConfig()->group(QString()); 0728 config.deleteGroup(); 0729 }