kis_image_config.cpp 11.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 *  Copyright (c) 2010 Dmitry Kazakov <dimula73@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kis_image_config.h"

#include <ksharedconfig.h>
22

23
#include <KoConfig.h>
24 25
#include <KoColorProfile.h>
#include <KoColorConversionTransformation.h>
26

27
#include "kis_debug.h"
28

29 30
#include <QThread>
#include <QApplication>
31
#include <QColor>
32
#include <QDir>
33

34 35 36
#include "kis_global.h"
#include <cmath>

37 38 39
#ifdef Q_OS_MAC
#include <errno.h>
#endif
40

41 42 43
KisImageConfig::KisImageConfig(bool readOnly)
    : m_config( KSharedConfig::openConfig()->group("")),
      m_readOnly(readOnly)
44 45 46 47 48
{
}

KisImageConfig::~KisImageConfig()
{
49 50
    if (m_readOnly) return;

51
    if (qApp->thread() != QThread::currentThread()) {
Boudewijn Rempt's avatar
Boudewijn Rempt committed
52
        dbgKrita << "KisImageConfig: requested config synchronization from nonGUI thread! Called from" << kisBacktrace();
53 54 55
        return;
    }

56 57 58
    m_config.sync();
}

59 60 61 62 63 64 65 66 67 68 69
bool KisImageConfig::enableProgressReporting(bool requestDefault) const
{
    return !requestDefault ?
        m_config.readEntry("enableProgressReporting", true) : true;
}

void KisImageConfig::setEnableProgressReporting(bool value)
{
    m_config.writeEntry("enableProgressReporting", value);
}

70
bool KisImageConfig::enablePerfLog(bool requestDefault) const
71
{
72 73 74 75 76 77 78
    return !requestDefault ?
        m_config.readEntry("enablePerfLog", false) :false;
}

void KisImageConfig::setEnablePerfLog(bool value)
{
    m_config.writeEntry("enablePerfLog", value);
79 80
}

81 82 83 84 85
qreal KisImageConfig::transformMaskOffBoundsReadArea() const
{
    return m_config.readEntry("transformMaskOffBoundsReadArea", 0.5);
}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
int KisImageConfig::updatePatchHeight() const
{
    return m_config.readEntry("updatePatchHeight", 512);
}

void KisImageConfig::setUpdatePatchHeight(int value)
{
    m_config.writeEntry("updatePatchHeight", value);
}

int KisImageConfig::updatePatchWidth() const
{
    return m_config.readEntry("updatePatchWidth", 512);
}

void KisImageConfig::setUpdatePatchWidth(int value)
{
    m_config.writeEntry("updatePatchWidth", value);
}

qreal KisImageConfig::maxCollectAlpha() const
{
    return m_config.readEntry("maxCollectAlpha", 2.5);
}

qreal KisImageConfig::maxMergeAlpha() const
{
    return m_config.readEntry("maxMergeAlpha", 1.);
}

qreal KisImageConfig::maxMergeCollectAlpha() const
{
    return m_config.readEntry("maxMergeCollectAlpha", 1.5);
}
120

121 122 123 124 125
qreal KisImageConfig::schedulerBalancingRatio() const
{
    /**
     * updates-queue-size / strokes-queue-size
     */
126
    return m_config.readEntry("schedulerBalancingRatio", 100.);
127 128
}

129 130 131 132 133
void KisImageConfig::setSchedulerBalancingRatio(qreal value)
{
    m_config.writeEntry("schedulerBalancingRatio", value);
}

134
int KisImageConfig::maxSwapSize(bool requestDefault) const
135
{
136 137
    return !requestDefault ?
        m_config.readEntry("maxSwapSize", 4096) : 4096; // in MiB
138 139 140 141 142 143 144 145 146 147 148 149
}

void KisImageConfig::setMaxSwapSize(int value)
{
    m_config.writeEntry("maxSwapSize", value);
}

int KisImageConfig::swapSlabSize() const
{
    return m_config.readEntry("swapSlabSize", 64); // in MiB
}

Dmitry Kazakov's avatar
Dmitry Kazakov committed
150
void KisImageConfig::setSwapSlabSize(int value)
151 152 153
{
    m_config.writeEntry("swapSlabSize", value);
}
Dmitry Kazakov's avatar
Dmitry Kazakov committed
154 155 156 157 158 159 160 161 162 163

int KisImageConfig::swapWindowSize() const
{
    return m_config.readEntry("swapWindowSize", 16); // in MiB
}

void KisImageConfig::setSwapWindowSize(int value)
{
    m_config.writeEntry("swapWindowSize", value);
}
164

165
int KisImageConfig::tilesHardLimit() const
166
{
167 168 169 170
    qreal hp = qreal(memoryHardLimitPercent()) / 100.0;
    qreal pp = qreal(memoryPoolLimitPercent()) / 100.0;

    return totalRAM() * hp * (1 - pp);
171 172
}

173
int KisImageConfig::tilesSoftLimit() const
174
{
175 176 177
    qreal sp = qreal(memorySoftLimitPercent()) / 100.0;

    return tilesHardLimit() * sp;
178 179 180 181
}

int KisImageConfig::poolLimit() const
{
182 183 184 185
    qreal hp = qreal(memoryHardLimitPercent()) / 100.0;
    qreal pp = qreal(memoryPoolLimitPercent()) / 100.0;

    return totalRAM() * hp * pp;
186 187
}

188
qreal KisImageConfig::memoryHardLimitPercent(bool requestDefault) const
189
{
190 191
    return !requestDefault ?
        m_config.readEntry("memoryHardLimitPercent", 50.) : 50.;
192 193
}

194
void KisImageConfig::setMemoryHardLimitPercent(qreal value)
195
{
196
    m_config.writeEntry("memoryHardLimitPercent", value);
197 198
}

199
qreal KisImageConfig::memorySoftLimitPercent(bool requestDefault) const
200
{
201 202
    return !requestDefault ?
        m_config.readEntry("memorySoftLimitPercent", 2.) : 2.;
203 204
}

205
void KisImageConfig::setMemorySoftLimitPercent(qreal value)
206 207 208 209
{
    m_config.writeEntry("memorySoftLimitPercent", value);
}

210
qreal KisImageConfig::memoryPoolLimitPercent(bool requestDefault) const
211
{
212 213
    return !requestDefault ?
        m_config.readEntry("memoryPoolLimitPercent", 2.) : 2.;
214 215 216 217 218 219 220
}

void KisImageConfig::setMemoryPoolLimitPercent(qreal value)
{
    m_config.writeEntry("memoryPoolLimitPercent", value);
}

221 222
QString KisImageConfig::swapDir(bool requestDefault)
{
223
    QString swap = QDir::tempPath();
224 225 226 227 228
    return !requestDefault ?
            m_config.readEntry("swaplocation", swap) : swap;
}

void KisImageConfig::setSwapDir(const QString &swapDir)
229
{
230
    m_config.writeEntry("swaplocation", swapDir);
231 232
}

233 234
int KisImageConfig::numberOfOnionSkins() const
{
235
    return m_config.readEntry("numberOfOnionSkins", 10);
236 237 238 239 240 241 242 243 244
}

void KisImageConfig::setNumberOfOnionSkins(int value)
{
    m_config.writeEntry("numberOfOnionSkins", value);
}

int KisImageConfig::onionSkinTintFactor() const
{
245
    return m_config.readEntry("onionSkinTintFactor", 192);
246 247 248 249 250 251 252 253 254
}

void KisImageConfig::setOnionSkinTintFactor(int value)
{
    m_config.writeEntry("onionSkinTintFactor", value);
}

int KisImageConfig::onionSkinOpacity(int offset) const
{
255 256 257 258 259 260 261 262 263
    int value = m_config.readEntry("onionSkinOpacity_" + QString::number(offset), -1);

    if (value < 0) {
        const int num = numberOfOnionSkins();
        const qreal dx = qreal(qAbs(offset)) / num;
        value = 0.7 * exp(-pow2(dx) / 0.5) * 255;
    }

    return value;
264 265 266 267 268 269 270
}

void KisImageConfig::setOnionSkinOpacity(int offset, int value)
{
    m_config.writeEntry("onionSkinOpacity_" + QString::number(offset), value);
}

271 272
bool KisImageConfig::onionSkinState(int offset) const
{
273 274
    bool enableByDefault = (qAbs(offset) <= 2);
    return m_config.readEntry("onionSkinState_" + QString::number(offset), enableByDefault);
275 276 277 278 279 280 281
}

void KisImageConfig::setOnionSkinState(int offset, bool value)
{
    m_config.writeEntry("onionSkinState_" + QString::number(offset), value);
}

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
QColor KisImageConfig::onionSkinTintColorBackward() const
{
    return m_config.readEntry("onionSkinTintColorBackward", QColor(Qt::red));
}

void KisImageConfig::setOnionSkinTintColorBackward(const QColor &value)
{
    m_config.writeEntry("onionSkinTintColorBackward", value);
}

QColor KisImageConfig::onionSkinTintColorForward() const
{
    return m_config.readEntry("oninSkinTintColorForward", QColor(Qt::green));
}

void KisImageConfig::setOnionSkinTintColorForward(const QColor &value)
{
    m_config.writeEntry("oninSkinTintColorForward", value);
}

302 303 304 305 306 307 308 309 310 311 312
bool KisImageConfig::lazyFrameCreationEnabled(bool requestDefault) const
{
    return !requestDefault ?
        m_config.readEntry("lazyFrameCreationEnabled", true) : true;
}

void KisImageConfig::setLazyFrameCreationEnabled(bool value)
{
    m_config.writeEntry("lazyFrameCreationEnabled", value);
}

313 314 315

#if defined Q_OS_LINUX
#include <sys/sysinfo.h>
316
#elif defined Q_OS_FREEBSD || defined Q_OS_NETBSD || defined Q_OS_OPENBSD
317
#include <sys/sysctl.h>
318 319
#elif defined Q_OS_WIN
#include <windows.h>
320
#elif defined Q_OS_MAC
321 322
#include <sys/types.h>
#include <sys/sysctl.h>
323 324
#endif

325
#include <kis_debug.h>
326 327 328 329 330

int KisImageConfig::totalRAM()
{
    // let's think that default memory size is 1000MiB
    int totalMemory = 1000; // MiB
331
    int error = 1;
332 333 334 335

#if defined Q_OS_LINUX
    struct sysinfo info;

336
    error = sysinfo(&info);
337 338
    if(!error) {
        totalMemory = info.totalram * info.mem_unit / (1UL << 20);
339
    }
340
#elif defined Q_OS_FREEBSD || defined Q_OS_NETBSD || defined Q_OS_OPENBSD
341
    u_long physmem;
342 343 344
#   if defined HW_PHYSMEM64 // NetBSD only
    int mib[] = {CTL_HW, HW_PHYSMEM64};
#   else
345
    int mib[] = {CTL_HW, HW_PHYSMEM};
346
#   endif
347 348
    size_t len = sizeof(physmem);

349
    error = sysctl(mib, 2, &physmem, &len, 0, 0);
350 351 352
    if(!error) {
        totalMemory = physmem >> 20;
    }
353 354 355 356 357
#elif defined Q_OS_WIN
    MEMORYSTATUSEX status;
    status.dwLength = sizeof(status);
    error  = !GlobalMemoryStatusEx(&status);

358
    if (!error) {
359 360
        totalMemory = status.ullTotalPhys >> 20;
    }
361

362 363 364 365
    // For 32 bit windows, the total memory available is at max the 2GB per process memory limit.
#   if defined ENV32BIT
    totalMemory = qMin(totalMemory, 2000);
#   endif
366
#elif defined Q_OS_MAC
367 368 369 370 371
    int mib[2] = { CTL_HW, HW_MEMSIZE };
    u_int namelen = sizeof(mib) / sizeof(mib[0]);
    uint64_t size;
    size_t len = sizeof(size);

372
    errno = 0;
373
    if (sysctl(mib, namelen, &size, &len, 0, 0) >= 0) {
374
        totalMemory = size >> 20;
375
        error = 0;
376
    }
377
    else {
Boudewijn Rempt's avatar
Boudewijn Rempt committed
378
        dbgKrita << "sysctl(\"hw.memsize\") raised error" << strerror(errno);
379
    }
380 381
#endif

Boudewijn Rempt's avatar
Boudewijn Rempt committed
382 383
    if (error) {
        warnKrita << "Cannot get the size of your RAM. Using 1 GiB by default.";
384 385 386
    }

    return totalMemory;
387
}
388 389 390 391 392 393 394 395 396 397 398

bool KisImageConfig::showAdditionalOnionSkinsSettings(bool requestDefault) const
{
    return !requestDefault ?
        m_config.readEntry("showAdditionalOnionSkinsSettings", true) : true;
}

void KisImageConfig::setShowAdditionalOnionSkinsSettings(bool value)
{
    m_config.writeEntry("showAdditionalOnionSkinsSettings", value);
}
399 400 401 402 403 404 405

KisProofingConfiguration *KisImageConfig::defaultProofingconfiguration()
{
    KisProofingConfiguration *proofingConfig= new KisProofingConfiguration();
    proofingConfig->proofingProfile = m_config.readEntry("defaultProofingProfileName", "Chemical proof");
    proofingConfig->proofingModel = m_config.readEntry("defaultProofingProfileModel", "CMYKA");
    proofingConfig->proofingDepth = m_config.readEntry("defaultProofingProfileDepth", "U8");
406
    proofingConfig->intent = (KoColorConversionTransformation::Intent)m_config.readEntry("defaultProofingProfileIntent", 3);
407 408 409 410 411 412 413 414 415 416
    if (m_config.readEntry("defaultProofingBlackpointCompensation", true)) {
        proofingConfig->conversionFlags  |= KoColorConversionTransformation::ConversionFlag::BlackpointCompensation;
    } else {
                proofingConfig->conversionFlags  = proofingConfig->conversionFlags & ~KoColorConversionTransformation::ConversionFlag::BlackpointCompensation;
    }
    QColor def;
    def =  m_config.readEntry("defaultProofingGamutwarning", QColor(Qt::gray));
    KoColor col;
    col.fromQColor(def);
    proofingConfig->warningColor = col;
417
    proofingConfig->adaptationState = (double)m_config.readEntry("defaultProofingAdaptationState", 1.0);
418 419 420
    return proofingConfig;
}

421
void KisImageConfig::setDefaultProofingConfig(const KoColorSpace *proofingSpace, int proofingIntent, bool blackPointCompensation, KoColor warningColor, double adaptationState)
422 423 424 425 426 427 428 429 430
{
    m_config.writeEntry("defaultProofingProfileName", proofingSpace->profile()->name());
    m_config.writeEntry("defaultProofingProfileModel", proofingSpace->colorModelId().id());
    m_config.writeEntry("defaultProofingProfileDepth", proofingSpace->colorDepthId().id());
    m_config.writeEntry("defaultProofingProfileIntent", proofingIntent);
    m_config.writeEntry("defaultProofingBlackpointCompensation", blackPointCompensation);
    QColor c;
    warningColor.toQColor(&c);
    m_config.writeEntry("defaultProofingGamutwarning", c);
431
    m_config.writeEntry("defaultProofingAdaptationState",adaptationState);
432
}