main.cc 20.6 KB
Newer Older
Boudewijn Rempt's avatar
Boudewijn Rempt committed
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
* Copyright (c) 1999 Matthias Elter <me@kde.org>
* Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
* Copyright (c) 2015 Boudewijn Rempt <boud@valdyas.org>
*
*  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.
*/
Boudewijn Rempt's avatar
Boudewijn Rempt committed
20

Boudewijn Rempt's avatar
Boudewijn Rempt committed
21
#include <stdlib.h>
22 23 24

#include <QString>
#include <QPixmap>
25
#include <kis_debug.h>
26 27
#include <QProcess>
#include <QProcessEnvironment>
28
#include <QStandardPaths>
29
#include <QDir>
30
#include <QDate>
31 32
#include <QLocale>
#include <QSettings>
33
#include <QByteArray>
34
#include <QMessageBox>
35
#include <QThread>
36

37
#if QT_VERSION >= 0x050900
38
#include <QOperatingSystemVersion>
39
#endif
40

41 42
#include <time.h>

43
#include <KisApplication.h>
44
#include <KoConfig.h>
45
#include <KoResourcePaths.h>
46
#include <kis_config.h>
47 48

#include "data/splash/splash_screen.xpm"
49
#include "data/splash/splash_holidays.xpm"
50 51
#include "data/splash/splash_screen_x2.xpm"
#include "data/splash/splash_holidays_x2.xpm"
52
#include "KisDocument.h"
53
#include "kis_splash_screen.h"
54
#include "KisPart.h"
55
#include "KisApplicationArguments.h"
56
#include <opengl/kis_opengl.h>
57
#include "input/KisQtWidgetsTweaker.h"
58 59
#include <KisUsageLogger.h>
#include <kis_image_config.h>
60

61
#if defined Q_OS_WIN
62
#include "config_use_qt_tablet_windows.h"
63
#include <windows.h>
64
#ifndef USE_QT_TABLET_WINDOWS
65
#include <kis_tablet_support_win.h>
66
#include <kis_tablet_support_win8.h>
67 68
#else
#include <dialogs/KisDlgCustomTabletResolution.h>
69
#endif
70
#include "config-high-dpi-scale-factor-rounding-policy.h"
71 72 73 74
#include "config-set-has-border-in-full-screen-default.h"
#ifdef HAVE_SET_HAS_BORDER_IN_FULL_SCREEN_DEFAULT
#include <QtPlatformHeaders/QWindowsWindowFunctions>
#endif
75
#include <QLibrary>
76
#endif
77

78 79
#if defined HAVE_KCRASH
#include <kcrash.h>
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
#elif defined USE_DRMINGW
namespace
{
void tryInitDrMingw()
{
    wchar_t path[MAX_PATH];
    QString pathStr = QCoreApplication::applicationDirPath().replace(L'/', L'\\') + QStringLiteral("\\exchndl.dll");
    if (pathStr.size() > MAX_PATH - 1) {
        return;
    }
    int pathLen = pathStr.toWCharArray(path);
    path[pathLen] = L'\0'; // toWCharArray doesn't add NULL terminator
    HMODULE hMod = LoadLibraryW(path);
    if (!hMod) {
        return;
    }
    // No need to call ExcHndlInit since the crash handler is installed on DllMain
    auto myExcHndlSetLogFileNameA = reinterpret_cast<BOOL (APIENTRY *)(const char *)>(GetProcAddress(hMod, "ExcHndlSetLogFileNameA"));
    if (!myExcHndlSetLogFileNameA) {
        return;
    }
    // Set the log file path to %LocalAppData%\kritacrash.log
    QString logFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation).replace(L'/', L'\\') + QStringLiteral("\\kritacrash.log");
    myExcHndlSetLogFileNameA(logFile.toLocal8Bit());
}
105 106
} // namespace
#endif
107

108 109 110
#ifdef Q_OS_WIN
namespace
{
111 112 113 114 115 116 117 118
typedef enum ORIENTATION_PREFERENCE {
    ORIENTATION_PREFERENCE_NONE = 0x0,
    ORIENTATION_PREFERENCE_LANDSCAPE = 0x1,
    ORIENTATION_PREFERENCE_PORTRAIT = 0x2,
    ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED = 0x4,
    ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED = 0x8
} ORIENTATION_PREFERENCE;
typedef BOOL WINAPI (*pSetDisplayAutoRotationPreferences_t)(
119 120
        ORIENTATION_PREFERENCE orientation
        );
121 122 123 124 125 126 127 128 129 130
void resetRotation()
{
    QLibrary user32Lib("user32");
    if (!user32Lib.load()) {
        qWarning() << "Failed to load user32.dll! This really should not happen.";
        return;
    }
    pSetDisplayAutoRotationPreferences_t pSetDisplayAutoRotationPreferences
            = reinterpret_cast<pSetDisplayAutoRotationPreferences_t>(user32Lib.resolve("SetDisplayAutoRotationPreferences"));
    if (!pSetDisplayAutoRotationPreferences) {
Boudewijn Rempt's avatar
Boudewijn Rempt committed
131
        dbgKrita << "Failed to load function SetDisplayAutoRotationPreferences";
132 133 134
        return;
    }
    bool result = pSetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_NONE);
Boudewijn Rempt's avatar
Boudewijn Rempt committed
135
    dbgKrita << "SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_NONE) returned" << result;
136
}
137
} // namespace
138
#endif
139

140
extern "C" int main(int argc, char **argv)
141
{
142

143 144
    // The global initialization of the random generator
    qsrand(time(0));
145
    bool runningInKDE = !qgetenv("KDE_FULL_SESSION").isEmpty();
146 147 148

#if defined HAVE_X11
    qputenv("QT_QPA_PLATFORM", "xcb");
149 150
#endif

151 152 153
    // Workaround a bug in QNetworkManager
    qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));

154
    // A per-user unique string, without /, because QLocalServer cannot use names with a / in it
155
    QString key = "Krita4" + QStandardPaths::writableLocation(QStandardPaths::HomeLocation).replace("/", "_");
156
    key = key.replace(":", "_").replace("\\","_");
157

158
    QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
159

160
    QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
161
    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
162

163 164 165 166
#if QT_VERSION >= 0x050900
    QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache, true);
#endif

167 168 169 170 171 172 173 174 175 176 177 178 179
#ifdef HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY
    // This rounding policy depends on a series of patches to Qt related to
    // https://bugreports.qt.io/browse/QTBUG-53022. These patches are applied
    // in ext_qt for WIndows (patches 0031-0036).
    //
    // The rounding policy can be set externally by setting the environment
    // variable `QT_SCALE_FACTOR_ROUNDING_POLICY` to one of the following:
    //   Round:            Round up for .5 and above.
    //   Ceil:             Always round up.
    //   Floor:            Always round down.
    //   RoundPreferFloor: Round up for .75 and above.
    //   PassThrough:      Don't round.
    //
180
    // The default is set to RoundPreferFloor for better behaviour than before,
181
    // but can be overridden by the above environment variable.
182
    QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor);
183 184
#endif

185
    const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
186
    QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
Boudewijn Rempt's avatar
Boudewijn Rempt committed
187

188
    bool singleApplication = true;
189 190
    bool enableOpenGLDebug = false;
    bool openGLDebugSynchronous = false;
191
    bool logUsage = true;
Boudewijn Rempt's avatar
Boudewijn Rempt committed
192
    {
193

194
        singleApplication = kritarc.value("EnableSingleApplication", true).toBool();
195
        if (kritarc.value("EnableHiDPI", true).toBool()) {
Boudewijn Rempt's avatar
Boudewijn Rempt committed
196 197 198 199 200
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        }
        if (!qgetenv("KRITA_HIDPI").isEmpty()) {
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        }
201 202 203 204 205
#ifdef HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY
        if (kritarc.value("EnableHiDPIFractionalScaling", true).toBool()) {
            QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
        }
#endif
206

207 208 209 210 211 212 213 214
        if (!qgetenv("KRITA_OPENGL_DEBUG").isEmpty()) {
            enableOpenGLDebug = true;
        } else {
            enableOpenGLDebug = kritarc.value("EnableOpenGLDebug", false).toBool();
        }
        if (enableOpenGLDebug && (qgetenv("KRITA_OPENGL_DEBUG") == "sync" || kritarc.value("OpenGLDebugSynchronous", false).toBool())) {
            openGLDebugSynchronous = true;
        }
215

216 217
        KisConfig::RootSurfaceFormat rootSurfaceFormat = KisConfig::rootSurfaceFormat(&kritarc);
        KisOpenGL::OpenGLRenderer preferredRenderer = KisOpenGL::RendererAuto;
218

219 220
        logUsage = kritarc.value("LogUsage", true).toBool();

221 222
        const QString preferredRendererString = kritarc.value("OpenGLRenderer", "auto").toString();
        preferredRenderer = KisOpenGL::convertConfigToOpenGLRenderer(preferredRendererString);
223

224 225
        const KisOpenGL::RendererConfig config =
            KisOpenGL::selectSurfaceConfig(preferredRenderer, rootSurfaceFormat, enableOpenGLDebug);
226

227
        KisOpenGL::setDefaultSurfaceConfig(config);
228 229 230
        KisOpenGL::setDebugSynchronous(openGLDebugSynchronous);

#ifdef Q_OS_WIN
231 232
        // HACK: https://bugs.kde.org/show_bug.cgi?id=390651
        resetRotation();
233
#endif
234
    }
235

236 237 238 239
    if (logUsage) {
        KisUsageLogger::initialize();
    }

240 241

    QString root;
242
    QString language;
243 244 245 246 247
    {
        // Create a temporary application to get the root
        QCoreApplication app(argc, argv);
        Q_UNUSED(app);
        root = KoResourcePaths::getApplicationRoot();
248 249
        QSettings languageoverride(configPath + QStringLiteral("/klanguageoverridesrc"), QSettings::IniFormat);
        languageoverride.beginGroup(QStringLiteral("Language"));
250
        language = languageoverride.value(qAppName(), "").toString();
251 252 253
    }


254
#ifdef Q_OS_LINUX
255 256 257 258 259 260
    {
        QByteArray originalXdgDataDirs = qgetenv("XDG_DATA_DIRS");
        if (originalXdgDataDirs.isEmpty()) {
            // We don't want to completely override the default
            originalXdgDataDirs = "/usr/local/share/:/usr/share/";
        }
261
        qputenv("XDG_DATA_DIRS", QFile::encodeName(root + "share") + ":" + originalXdgDataDirs);
262
    }
263
#else
264
    qputenv("XDG_DATA_DIRS", QFile::encodeName(root + "share"));
265 266
#endif

Boudewijn Rempt's avatar
Boudewijn Rempt committed
267
    dbgKrita << "Setting XDG_DATA_DIRS" << qgetenv("XDG_DATA_DIRS");
268

luz paz's avatar
luz paz committed
269
    // Now that the paths are set, set the language. First check the override from the language
270
    // selection dialog.
Boudewijn Rempt's avatar
Boudewijn Rempt committed
271

Boudewijn Rempt's avatar
Boudewijn Rempt committed
272
    dbgKrita << "Override language:" << language;
273
    bool rightToLeft = false;
274 275 276
    if (!language.isEmpty()) {
        KLocalizedString::setLanguages(language.split(":"));
        // And override Qt's locale, too
277
        qputenv("LANG", language.split(":").first().toLocal8Bit());
278 279
        QLocale locale(language.split(":").first());
        QLocale::setDefault(locale);
280 281 282 283 284 285 286

        const QStringList rtlLanguages = QStringList()
                << "ar" << "dv" << "he" << "ha" << "ku" << "fa" << "ps" << "ur" << "yi";

        if (rtlLanguages.contains(language.split(':').first())) {
            rightToLeft = true;
        }
287 288
    }
    else {
289 290
        dbgKrita << "Qt UI languages:" << QLocale::system().uiLanguages() << qgetenv("LANG");

291 292 293
        // And if there isn't one, check the one set by the system.
        QLocale locale = QLocale::system();
        if (locale.name() != QStringLiteral("en")) {
294 295
            QStringList uiLanguages = locale.uiLanguages();
            for (QString &uiLanguage : uiLanguages) {
296 297 298 299 300 301 302 303 304 305 306 307 308 309

                // This list of language codes that can have a specifier should
                // be extended whenever we have translations that need it; right
                // now, only en, pt, zh are in this situation.

                if (uiLanguage.startsWith("en") || uiLanguage.startsWith("pt")) {
                    uiLanguage.replace(QChar('-'), QChar('_'));
                }
                else if (uiLanguage.startsWith("zh-Hant") || uiLanguage.startsWith("zh-TW")) {
                    uiLanguage = "zh_TW";
                }
                else if (uiLanguage.startsWith("zh-Hans") || uiLanguage.startsWith("zh-CN")) {
                    uiLanguage = "zh_CN";
                }
310
            }
311

312 313 314
            for (int i = 0; i < uiLanguages.size(); i++) {
                QString uiLanguage = uiLanguages[i];
                // Strip the country code
315 316
                int idx = uiLanguage.indexOf(QChar('-'));

317 318
                if (idx != -1) {
                    uiLanguage = uiLanguage.left(idx);
319
                    uiLanguages.replace(i, uiLanguage);
320 321
                }
            }
322
            dbgKrita << "Converted ui languages:" << uiLanguages;
323
            qputenv("LANG", uiLanguages.first().toLocal8Bit());
324 325 326 327 328 329
#ifdef Q_OS_MAC
            // See https://bugs.kde.org/show_bug.cgi?id=396370
            KLocalizedString::setLanguages(QStringList() << uiLanguages.first());
#else
            KLocalizedString::setLanguages(QStringList() << uiLanguages);
#endif
330
        }
Boudewijn Rempt's avatar
Boudewijn Rempt committed
331
    }
332

333 334 335
#if defined Q_OS_WIN && defined USE_QT_TABLET_WINDOWS && defined QT_HAS_WINTAB_SWITCH
    const bool forceWinTab = !KisConfig::useWin8PointerInputNoApp(&kritarc);
    QCoreApplication::setAttribute(Qt::AA_MSWindowsUseWinTabAPI, forceWinTab);
336 337 338 339 340 341 342

    if (qEnvironmentVariableIsEmpty("QT_WINTAB_DESKTOP_RECT") &&
        qEnvironmentVariableIsEmpty("QT_IGNORE_WINTAB_MAPPING")) {

        QRect customTabletRect;
        KisDlgCustomTabletResolution::Mode tabletMode =
            KisDlgCustomTabletResolution::getTabletMode(&customTabletRect);
343
        KisDlgCustomTabletResolution::applyConfiguration(tabletMode, customTabletRect);
344
    }
345 346
#endif

347 348
    // first create the application so we can create a pixmap
    KisApplication app(key, argc, argv);
349

350 351 352 353 354 355
#ifdef HAVE_SET_HAS_BORDER_IN_FULL_SCREEN_DEFAULT
    if (QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL)) {
        QWindowsWindowFunctions::setHasBorderInFullScreenDefault(true);
    }
#endif

356 357
    KisUsageLogger::writeHeader();

358 359 360 361 362 363 364 365
    if (!language.isEmpty()) {
        if (rightToLeft) {
            app.setLayoutDirection(Qt::RightToLeft);
        }
        else {
            app.setLayoutDirection(Qt::LeftToRight);
        }
    }
366 367
    KLocalizedString::setApplicationDomain("krita");

Boudewijn Rempt's avatar
Boudewijn Rempt committed
368 369
    dbgKrita << "Available translations" << KLocalizedString::availableApplicationTranslations();
    dbgKrita << "Available domain translations" << KLocalizedString::availableDomainTranslations("krita");
370 371


372
#ifdef Q_OS_WIN
Boudewijn Rempt's avatar
Boudewijn Rempt committed
373
    QDir appdir(KoResourcePaths::getApplicationRoot());
374
    QString path = qgetenv("PATH");
375
    qputenv("PATH", QFile::encodeName(appdir.absolutePath() + "/bin" + ";"
376 377 378 379
                                      + appdir.absolutePath() + "/lib" + ";"
                                      + appdir.absolutePath() + "/Frameworks" + ";"
                                      + appdir.absolutePath() + ";"
                                      + path));
380

Boudewijn Rempt's avatar
Boudewijn Rempt committed
381
    dbgKrita << "PATH" << qgetenv("PATH");
382 383
#endif

384 385 386 387 388
    if (qApp->applicationDirPath().contains(KRITA_BUILD_DIR)) {
        qFatal("FATAL: You're trying to run krita from the build location. You can only run Krita from the installation location.");
    }


389 390 391 392 393
#if defined HAVE_KCRASH
    KCrash::initialize();
#elif defined USE_DRMINGW
    tryInitDrMingw();
#endif
394

395 396 397 398 399
    // If we should clear the config, it has to be done as soon as possible after
    // KisApplication has been created. Otherwise the config file may have been read
    // and stored in a KConfig object we have no control over.
    app.askClearConfig();

400 401
    KisApplicationArguments args(app);

402
    if (singleApplication && app.isRunning()) {
403 404
        // only pass arguments to main instance if they are not for batch processing
        // any batch processing would be done in this separate instance
405
        const bool batchRun = args.exportAs() || args.exportSequence();
406 407

        if (!batchRun) {
408
            QByteArray ba = args.serialize();
409 410 411
            if (app.sendMessage(ba)) {
                return 0;
            }
412 413
        }
    }
414

415 416 417 418
    if (!runningInKDE) {
        // Icons in menus are ugly and distracting
        app.setAttribute(Qt::AA_DontShowIconsInMenus);
    }
419

420
    app.installEventFilter(KisQtWidgetsTweaker::instance());
421

422 423 424 425 426 427 428 429
    if (!args.noSplash()) {
        // then create the pixmap from an xpm: we cannot get the
        // location of our datadir before we've started our components,
        // so use an xpm.
        QDate currentDate = QDate::currentDate();
        QWidget *splash = 0;
        if (currentDate > QDate(currentDate.year(), 12, 4) ||
                currentDate < QDate(currentDate.year(), 1, 9)) {
430
            splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_holidays_xpm), QPixmap(splash_holidays_x2_xpm));
431 432
        }
        else {
433
            splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_screen_xpm), QPixmap(splash_screen_x2_xpm));
434
        }
435

436 437
        app.setSplashScreen(splash);
    }
438

439
#if defined Q_OS_WIN
440
    KisConfig cfg(false);
441 442 443 444 445 446 447 448 449 450 451 452 453 454
    bool supportedWindowsVersion = true;
#if QT_VERSION >= 0x050900
    QOperatingSystemVersion osVersion = QOperatingSystemVersion::current();
    if (osVersion.type() == QOperatingSystemVersion::Windows) {
        if (osVersion.majorVersion() >= QOperatingSystemVersion::Windows7.majorVersion()) {
            supportedWindowsVersion  = true;
        }
        else {
            supportedWindowsVersion  = false;
            if (cfg.readEntry("WarnedAboutUnsupportedWindows", false)) {
                QMessageBox::information(0,
                                         i18nc("@title:window", "Krita: Warning"),
                                         i18n("You are running an unsupported version of Windows: %1.\n"
                                              "This is not recommended. Do not report any bugs.\n"
455
                                              "Please update to a supported version of Windows: Windows 7, 8, 8.1 or 10.", osVersion.name()));
456 457 458 459 460 461
                cfg.writeEntry("WarnedAboutUnsupportedWindows", true);

            }
        }
    }
#endif
462
#ifndef USE_QT_TABLET_WINDOWS
463
    {
464 465 466 467 468
        if (cfg.useWin8PointerInput() && !KisTabletSupportWin8::isAvailable()) {
            cfg.setUseWin8PointerInput(false);
        }
        if (!cfg.useWin8PointerInput()) {
            bool hasWinTab = KisTabletSupportWin::init();
469
            if (!hasWinTab && supportedWindowsVersion) {
470 471 472 473 474 475
                if (KisTabletSupportWin8::isPenDeviceAvailable()) {
                    // Use WinInk automatically
                    cfg.setUseWin8PointerInput(true);
                } else if (!cfg.readEntry("WarnedAboutMissingWinTab", false)) {
                    if (KisTabletSupportWin8::isAvailable()) {
                        QMessageBox::information(nullptr,
476 477 478
                                                 i18n("Krita Tablet Support"),
                                                 i18n("Cannot load WinTab driver and no Windows Ink pen devices are found. If you have a drawing tablet, please make sure the tablet driver is properly installed."),
                                                 QMessageBox::Ok, QMessageBox::Ok);
479 480
                    } else {
                        QMessageBox::information(nullptr,
481 482 483
                                                 i18n("Krita Tablet Support"),
                                                 i18n("Cannot load WinTab driver. If you have a drawing tablet, please make sure the tablet driver is properly installed."),
                                                 QMessageBox::Ok, QMessageBox::Ok);
484 485 486 487 488
                    }
                    cfg.writeEntry("WarnedAboutMissingWinTab", true);
                }
            }
        }
489 490 491 492 493
        if (cfg.useWin8PointerInput()) {
            KisTabletSupportWin8 *penFilter = new KisTabletSupportWin8();
            if (penFilter->init()) {
                // penFilter.registerPointerDeviceNotifications();
                app.installNativeEventFilter(penFilter);
Boudewijn Rempt's avatar
Boudewijn Rempt committed
494
                dbgKrita << "Using Win8 Pointer Input for tablet support";
495
            } else {
Boudewijn Rempt's avatar
Boudewijn Rempt committed
496
                dbgKrita << "No Win8 Pointer Input available";
497 498 499 500
                delete penFilter;
            }
        }
    }
501 502 503 504 505 506 507 508 509
#elif defined QT_HAS_WINTAB_SWITCH

    // Check if WinTab/WinInk has actually activated
    const bool useWinTabAPI = app.testAttribute(Qt::AA_MSWindowsUseWinTabAPI);

    if (useWinTabAPI != !cfg.useWin8PointerInput()) {
        cfg.setUseWin8PointerInput(useWinTabAPI);
    }

510
#endif
511 512
#endif

513
    if (!app.start(args)) {
514
        return 1;
515 516
    }

517 518 519
#if QT_VERSION >= 0x050700
    app.setAttribute(Qt::AA_CompressHighFrequencyEvents, false);
#endif
520

521 522
    // Set up remote arguments.
    QObject::connect(&app, SIGNAL(messageReceived(QByteArray,QObject*)),
523
                     &app, SLOT(remoteArguments(QByteArray,QObject*)));
524 525

    QObject::connect(&app, SIGNAL(fileOpenRequest(QString)),
526
                     &app, SLOT(fileOpenRequested(QString)));
527

528 529 530 531 532 533 534
    // Hardware information
    KisUsageLogger::write("\nHardware Information\n");
    KisUsageLogger::write(QString("  GPU Acceleration: %1").arg(kritarc.value("OpenGLRenderer", "auto").toString()));
    KisUsageLogger::write(QString("  Memory: %1 Mb").arg(KisImageConfig(true).totalRAM()));
    KisUsageLogger::write(QString("  Number of Cores: %1").arg(QThread::idealThreadCount()));
    KisUsageLogger::write(QString("  Swap Location: %1\n").arg(KisImageConfig(true).swapDir()));

535
    int state = app.exec();
536

Boudewijn Rempt's avatar
Boudewijn Rempt committed
537
    {
538
        QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
Boudewijn Rempt's avatar
Boudewijn Rempt committed
539 540
        kritarc.setValue("canvasState", "OPENGL_SUCCESS");
    }
541

542 543 544 545
    if (logUsage) {
        KisUsageLogger::close();
    }

Cyrille Berger's avatar
Cyrille Berger committed
546
    return state;
547
}