Krita Source Code Documentation
Loading...
Searching...
No Matches
KisApplication.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
3 * SPDX-FileCopyrightText: 2012 Boudewijn Rempt <boud@valdyas.org>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#include "KisApplication.h"
9
10#include <stdlib.h>
11#ifdef Q_OS_WIN
12#include <windows.h>
13#include <tchar.h>
15#endif
16
17#ifdef Q_OS_MACOS
18#include "osx.h"
20#endif
21
22#ifdef Q_OS_ANDROID
23#include "KisAndroidDonations.h"
24#endif
25
26#include <QStandardPaths>
27#include <QScreen>
28#include <QDir>
29#include <QFile>
30#include <QLocale>
31#include <QMessageBox>
32#include <QProcessEnvironment>
33#include <QStringList>
34#include <QStyle>
35#include <QStyleFactory>
36#include <QSysInfo>
37#include <QTimer>
38#include <QWidget>
39#include <QImageReader>
40#include <QImageWriter>
41#include <QThread>
42
43#include <klocalizedstring.h>
44#include <kdesktopfile.h>
45#include <kconfig.h>
46#include <kconfiggroup.h>
47#include <kaboutdata.h>
48
49#include <KoDockRegistry.h>
50#include <KoToolRegistry.h>
52#include <KoPluginLoader.h>
53#include <KoShapeRegistry.h>
54#include "KoConfig.h"
55#include <KoResourcePaths.h>
56#include <KisMimeDatabase.h>
57#include "thememanager.h"
58#include "KisDocument.h"
59#include "KisMainWindow.h"
61#include "KisPart.h"
62#include <kis_icon.h>
63#include "kis_splash_screen.h"
64#include "kis_config.h"
65#include "kis_config_notifier.h"
67#include <filter/kis_filter.h>
76#include <kis_debug.h>
77#include "kis_action_registry.h"
78#include <KoResourceServer.h>
81#include "opengl/kis_opengl.h"
84#include "KisViewManager.h"
85#include <KisUsageLogger.h>
86
87#include <KritaVersionWrapper.h>
89
90#include <KisResourceCacheDb.h>
91#include <KisResourceLocator.h>
92#include <KisResourceLoader.h>
94
96#include <kis_gbr_brush.h>
97#include <kis_png_brush.h>
98#include <kis_svg_brush.h>
99#include <kis_imagepipe_brush.h>
100#include <KoColorSet.h>
101#include <KoSegmentGradient.h>
102#include <KoStopGradient.h>
103#include <KoPattern.h>
105#include <KisSessionResource.h>
109
113
116#include "kis_file_layer.h"
117#include "kis_group_layer.h"
120#include <QThreadStorage>
122
123#include <kis_psd_layer_style.h>
124
125#include <config-seexpr.h>
126#include <config-safe-asserts.h>
127
130
131#include <config-qt-patches-present.h>
132#include <config-use-surface-color-management-api.h>
133
134#if KRITA_USE_SURFACE_COLOR_MANAGEMENT_API
135
136#include <QWindow>
137#include <QPlatformSurfaceEvent>
139
140#endif /* KRITA_USE_SURFACE_COLOR_MANAGEMENT_API */
141
142namespace {
143const QTime appStartTime(QTime::currentTime());
144}
145
146namespace {
147struct AppRecursionInfo {
148 ~AppRecursionInfo() {
149 KIS_SAFE_ASSERT_RECOVER_NOOP(!eventRecursionCount);
150 KIS_SAFE_ASSERT_RECOVER_NOOP(postponedSynchronizationEvents.empty());
151 }
152
153 int eventRecursionCount {0};
154 std::queue<KisSynchronizedConnectionEvent> postponedSynchronizationEvents;
155};
156
157struct AppRecursionGuard {
158 AppRecursionGuard(AppRecursionInfo *info)
159 : m_info(info)
160 {
161 m_info->eventRecursionCount++;
162 }
163
164 ~AppRecursionGuard()
165 {
166 m_info->eventRecursionCount--;
167 }
168private:
169 AppRecursionInfo *m_info {0};
170};
171
172}
173
180Q_GLOBAL_STATIC(QThreadStorage<AppRecursionInfo>, s_recursionInfo)
181
183{
184public:
187 KisAutoSaveRecoveryDialog *autosaveDialog {0};
188 KisLongPressEventFilter *longPressEventFilter {nullptr};
189 QPointer<KisMainWindow> mainWindow; // The first mainwindow we create on startup
190 bool batchRun {false};
193 QScopedPointer<KisExtendedModifiersMapperPluginInterface> extendedModifiersPluginInterface;
194#ifdef Q_OS_ANDROID
195 KisAndroidDonations *androidDonations {nullptr};
196#endif
197};
198
200{
201public:
202 ResetStarting(KisSplashScreen *splash, int fileCount)
203 : m_splash(splash)
204 , m_fileCount(fileCount)
205 {
206 }
207
209
210 if (m_splash) {
211 m_splash->hide();
212 m_splash->deleteLater();
213 }
214 }
215
218};
219
220KisApplication::KisApplication(const QString &key, int &argc, char **argv)
221 : QtSingleApplication(key, argc, argv)
222 , d(new Private)
223{
224#ifdef Q_OS_ANDROID
225 // The hardware renderer backend on Android doesn't support proper stacking,
226 // causing windows with QtQuick widgets to always stack behind everything
227 // else, including our own dialog decorations.
228 qputenv("QT_QUICK_BACKEND", "software");
229#endif
230#ifdef Q_OS_MACOS
232#endif
233
234 QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath());
235
236 {
239
240 KAboutData aboutData("krita",
241 i18n("Krita"),
243 i18nc("@title", "Krita is the full-featured digital art studio"),
244 KAboutLicense::GPL,
245 i18nc("@info:credit", "© 1999–2026 The Krita Developers"));
246 aboutData.setHomepage(QStringLiteral("https://krita.org"));
247 aboutData.setOrganizationDomain("krita.org");
248
249 // this call sets corresponding fields of QApplication as well
250 KAboutData::setApplicationData(aboutData);
251
252 // Note: Qt docs suggest we set organization name, but if we do, we get resource
253 // paths of the form of krita/krita, which is weird.
254 KIS_SAFE_ASSERT_RECOVER(this->organizationName().isEmpty()) {
255 this->setOrganizationName("");
256 }
257 }
258
259#ifndef Q_OS_MACOS
260 setWindowIcon(KisIconUtils::loadIcon("krita-branding"));
261#endif
262
263 if (qgetenv("KRITA_NO_STYLE_OVERRIDE").isEmpty()) {
264
265#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
266 QStringList styles = QStringList() << "haiku" << "macintosh" << "breeze" << "fusion";
267#else
268 QStringList styles = QStringList() << "haiku" << "macos" << "breeze" << "fusion";
269#endif
270 if (!styles.contains(style()->objectName().toLower())) {
271 Q_FOREACH (const QString & style, styles) {
272 if (!setStyle(style)) {
273 qDebug() << "No" << style << "available.";
274 }
275 else {
276 qDebug() << "Set style" << style;
277 break;
278 }
279 }
280 }
281
282 // if style is set from config, try to load that
283 KisConfig cfg(true);
284 QString widgetStyleFromConfig = cfg.widgetStyle();
285 if(widgetStyleFromConfig != "") {
286 qApp->setStyle(widgetStyleFromConfig);
287#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
288 } else if (style()->objectName().toLower() == "macintosh") {
289 // if no configured style on macOS, default to Fusion
290 qApp->setStyle("fusion");
291 }
292#else
293 } else if (style()->objectName().toLower() == "macos") {
294 // if no configured style on macOS, default to Fusion
295 qApp->setStyle("fusion");
296 }
297#endif
298
299 }
300 else {
301 qDebug() << "Style override disabled, using" << style()->objectName();
302 }
303
307 {
308 d->extendedModifiersPluginInterface.reset(KisPlatformPluginInterfaceFactory::instance()->createExtendedModifiersMapper());
309 }
310
311 // store the style name
312 qApp->setProperty(currentUnderlyingStyleNameProperty, style()->objectName());
314
315
316#if KRITA_USE_SURFACE_COLOR_MANAGEMENT_API
317
322 struct PlatformWindowCreationFilter : QObject
323 {
324 using QObject::QObject;
325
326 bool eventFilter(QObject *watched, QEvent *event) override {
327 if (event->type() == QEvent::PlatformSurface) {
328 QWidget *widget = qobject_cast<QWidget*>(watched);
329 if (!widget) return false;
330
335 if (watched->property("krita_skip_srgb_surface_manager_assignment").toBool()) {
336 return false;
337 }
338
339 QPlatformSurfaceEvent *surfaceEvent = static_cast<QPlatformSurfaceEvent*>(event);
340 if (surfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
341 QWindow *nativeWindow = widget->windowHandle();
342 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(widget->windowHandle(), false);
343
344 if (!nativeWindow->findChild<KisSRGBSurfaceColorSpaceManager*>()) {
346 }
347 }
348 }
349
350 return false;
351 }
352 };
353
354 this->installEventFilter(new PlatformWindowCreationFilter(this));
355#endif /* KRITA_USE_SURFACE_COLOR_MANAGEMENT_API */
356}
357
358#if defined(Q_OS_WIN) && defined(ENV32BIT)
359typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
360
361LPFN_ISWOW64PROCESS fnIsWow64Process;
362
363BOOL isWow64()
364{
365 BOOL bIsWow64 = FALSE;
366
367 //IsWow64Process is not available on all supported versions of Windows.
368 //Use GetModuleHandle to get a handle to the DLL that contains the function
369 //and GetProcAddress to get a pointer to the function if available.
370
371 fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
372 GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
373
374 if(0 != fnIsWow64Process)
375 {
376 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
377 {
378 //handle error
379 }
380 }
381 return bIsWow64;
382}
383#endif
384
386{
387 Q_UNUSED(args)
388 // There are no globals to initialize from the arguments now. There used
389 // to be the `dpi` argument, but it doesn't do anything anymore.
390}
391
393{
394 // All Krita's resource types
395 KoResourcePaths::addAssetType("markers", "data", "/styles/");
396 KoResourcePaths::addAssetType("kis_pics", "data", "/pics/");
397 KoResourcePaths::addAssetType("kis_images", "data", "/images/");
398 KoResourcePaths::addAssetType("metadata_schema", "data", "/metadata/schemas/");
399 KoResourcePaths::addAssetType("gmic_definitions", "data", "/gmic/");
400 KoResourcePaths::addAssetType("kis_shortcuts", "data", "/shortcuts/");
401 KoResourcePaths::addAssetType("kis_actions", "data", "/actions");
402 KoResourcePaths::addAssetType("kis_actions", "data", "/pykrita");
403 KoResourcePaths::addAssetType("icc_profiles", "data", "/color/icc");
404 KoResourcePaths::addAssetType("icc_profiles", "data", "/profiles/");
405 KoResourcePaths::addAssetType("tags", "data", "/tags/");
406 KoResourcePaths::addAssetType("templates", "data", "/templates");
407 KoResourcePaths::addAssetType("pythonscripts", "data", "/pykrita");
408 KoResourcePaths::addAssetType("preset_icons", "data", "/preset_icons");
409#if defined HAVE_SEEXPR
410 KoResourcePaths::addAssetType(ResourceType::SeExprScripts, "data", "/seexpr_scripts/", true);
411#endif
412
413 // Make directories for all resources we can save, and tags
414 KoResourcePaths::saveLocation("data", "/asl/", true);
415 KoResourcePaths::saveLocation("data", "/css_styles/", true);
416 KoResourcePaths::saveLocation("data", "/input/", true);
417 KoResourcePaths::saveLocation("data", "/pykrita/", true);
418 KoResourcePaths::saveLocation("data", "/color-schemes/", true);
419 KoResourcePaths::saveLocation("data", "/preset_icons/", true);
420 KoResourcePaths::saveLocation("data", "/preset_icons/tool_icons/", true);
421 KoResourcePaths::saveLocation("data", "/preset_icons/emblem_icons/", true);
422}
423
424
425bool KisApplication::event(QEvent *event)
426{
427
428 #ifdef Q_OS_MACOS
429 if (event->type() == QEvent::FileOpen) {
430 QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
431 fileOpenRequested(openEvent->file());
432 return true;
433 }
434 #endif
435 return QApplication::event(event);
436}
437
438
440{
442
444 QStringList() << "application/x-krita-paintoppreset"));
445
446 reg->add(new KisResourceLoader<KisGbrBrush>(ResourceSubType::GbrBrushes, ResourceType::Brushes, i18n("Brush tips"), QStringList() << "image/x-gimp-brush"));
447 reg->add(new KisResourceLoader<KisImagePipeBrush>(ResourceSubType::GihBrushes, ResourceType::Brushes, i18n("Brush tips"), QStringList() << "image/x-gimp-brush-animated"));
448 reg->add(new KisResourceLoader<KisSvgBrush>(ResourceSubType::SvgBrushes, ResourceType::Brushes, i18n("Brush tips"), QStringList() << "image/svg+xml"));
450
451 reg->add(new KisResourceLoader<KoSegmentGradient>(ResourceSubType::SegmentedGradients, ResourceType::Gradients, i18n("Gradients"), QStringList() << "application/x-gimp-gradient"));
453
464
465
466 reg->add(new KisResourceLoader<KoPattern>(ResourceType::Patterns, ResourceType::Patterns, i18n("Patterns"), {"application/x-gimp-pattern", "image/x-gimp-pat", "application/x-gimp-pattern", "image/bmp", "image/jpeg", "image/png", "image/tiff"}));
467 reg->add(new KisResourceLoader<KisWorkspaceResource>(ResourceType::Workspaces, ResourceType::Workspaces, i18n("Workspaces"), QStringList() << "application/x-krita-workspace"));
468 reg->add(new KisResourceLoader<KoSvgSymbolCollectionResource>(ResourceType::Symbols, ResourceType::Symbols, i18n("SVG symbol libraries"), QStringList() << "image/svg+xml"));
469 reg->add(new KisResourceLoader<KisWindowLayoutResource>(ResourceType::WindowLayouts, ResourceType::WindowLayouts, i18n("Window layouts"), QStringList() << "application/x-krita-windowlayout"));
470 reg->add(new KisResourceLoader<KisSessionResource>(ResourceType::Sessions, ResourceType::Sessions, i18n("Sessions"), QStringList() << "application/x-krita-session"));
471 reg->add(new KisResourceLoader<KoGamutMask>(ResourceType::GamutMasks, ResourceType::GamutMasks, i18n("Gamut masks"), QStringList() << "application/x-krita-gamutmasks"));
472#if defined HAVE_SEEXPR
473 reg->add(new KisResourceLoader<KisSeExprScript>(ResourceType::SeExprScripts, ResourceType::SeExprScripts, i18n("SeExpr Scripts"), QStringList() << "application/x-krita-seexpr-script"));
474#endif
475 // XXX: this covers only individual styles, not the library itself!
478 i18nc("Resource type name", "Layer styles"),
479 QStringList() << "application/x-photoshop-style"));
480
481 reg->add(new KisResourceLoader<KoFontFamily>(ResourceType::FontFamilies, ResourceType::FontFamilies, i18n("Font Families"), QStringList() << "application/x-font-ttf" << "application/x-font-otf"));
482 reg->add(new KisResourceLoader<KoCssStylePreset>(ResourceType::CssStyles, ResourceType::CssStyles, i18n("Style Presets"), QStringList() << "image/svg+xml"));
483
485
486#ifndef Q_OS_ANDROID
487 QString databaseLocation = KoResourcePaths::getAppDataLocation();
488#else
489 // Sqlite doesn't support content URIs (obviously). So, we make database location unconfigurable on android.
490 QString databaseLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
491#endif
492
493 if (!KisResourceCacheDb::initialize(databaseLocation)) {
494 QMessageBox::critical(qApp->activeWindow(), i18nc("@title:window", "Krita: Fatal error"), i18n("%1\n\nKrita will quit now.", KisResourceCacheDb::lastError()));
495 }
496
498 connect(KisResourceLocator::instance(), SIGNAL(progressMessage(const QString&)), this, SLOT(setSplashScreenLoadingText(const QString&)));
499 if (r != KisResourceLocator::LocatorError::Ok && qApp->inherits("KisApplication")) {
500 QMessageBox::critical(qApp->activeWindow(), i18nc("@title:window", "Krita: Fatal error"), KisResourceLocator::instance()->errorMessages().join('\n') + i18n("\n\nKrita will quit now."));
501 return false;
502 }
503 return true;
504}
505
521
523{
524 KisConfig cfg(false);
525
526#if defined(Q_OS_WIN)
527#ifdef ENV32BIT
528
529 if (isWow64() && !cfg.readEntry("WarnedAbout32Bits", false)) {
530 QMessageBox::information(qApp->activeWindow(),
531 i18nc("@title:window", "Krita: Warning"),
532 i18n("You are running a 32 bits build on a 64 bits Windows.\n"
533 "This is not recommended.\n"
534 "Please download and install the x64 build instead."));
535 cfg.writeEntry("WarnedAbout32Bits", true);
536
537 }
538#endif
539#endif
540
541 QString opengl = cfg.canvasState();
542 if (opengl == "OPENGL_NOT_TRIED" ) {
543 cfg.setCanvasState("TRY_OPENGL");
544 }
545 else if (opengl != "OPENGL_SUCCESS" && opengl != "TRY_OPENGL") {
546 cfg.setCanvasState("OPENGL_FAILED");
547 }
548
549 setSplashScreenLoadingText(i18n("Initializing Globals..."));
550 processEvents();
551 initializeGlobals(args);
552
553 const bool doNewImage = args.doNewImage();
554 const bool doTemplate = args.doTemplate();
555 const bool exportAs = args.exportAs();
556 const bool exportSequence = args.exportSequence();
557 const QString exportFileName = args.exportFileName();
558
559 d->batchRun = (exportAs || exportSequence || !exportFileName.isEmpty());
560 const bool needsMainWindow = (!exportAs && !exportSequence);
561 // only show the mainWindow when no command-line mode option is passed
562 bool showmainWindow = (!exportAs && !exportSequence); // would be !batchRun;
563
564 const bool showSplashScreen = !d->batchRun && qEnvironmentVariableIsEmpty("NOSPLASH");
565 if (showSplashScreen && d->splashScreen) {
566 d->splashScreen->show();
567 d->splashScreen->repaint();
568 processEvents();
569 }
570
571 KConfigGroup group(KSharedConfig::openConfig(), "theme");
572#ifndef Q_OS_HAIKU
573 Digikam::ThemeManager themeManager;
574 themeManager.setCurrentTheme(group.readEntry("Theme", "Krita dark"));
575#endif
576
577 ResetStarting resetStarting(d->splashScreen, args.filenames().count()); // remove the splash when done
578 Q_UNUSED(resetStarting);
579
580 // Make sure we can save resources and tags
581 setSplashScreenLoadingText(i18n("Adding resource types..."));
582 processEvents();
584
585 setSplashScreenLoadingText(i18n("Loading plugins..."));
586 processEvents();
587 // Load the plugins
588 loadPlugins();
589
590 // Load all resources
591 setSplashScreenLoadingText(i18n("Loading resources..."));
592 processEvents();
593 if (!registerResources()) {
594 return false;
595 }
596
597 KisPart *kisPart = KisPart::instance();
598 if (needsMainWindow) {
599 // show a mainWindow asap, if we want that
600 setSplashScreenLoadingText(i18n("Loading Main Window..."));
601 processEvents();
602
603
604 bool sessionNeeded = true;
605 auto sessionMode = cfg.sessionOnStartup();
606
607 if (!args.session().isEmpty()) {
608 sessionNeeded = !kisPart->restoreSession(args.session());
609 } else if (sessionMode == KisConfig::SOS_ShowSessionManager) {
610 showmainWindow = false;
611 sessionNeeded = false;
612 kisPart->showSessionManager();
613 } else if (sessionMode == KisConfig::SOS_PreviousSession) {
614 KConfigGroup sessionCfg = KSharedConfig::openConfig()->group("session");
615 const QString &sessionName = sessionCfg.readEntry("previousSession");
616
617 sessionNeeded = !kisPart->restoreSession(sessionName);
618 }
619
620 if (sessionNeeded) {
621 kisPart->startBlankSession();
622 }
623
624 if (!args.windowLayout().isEmpty()) {
626 KisWindowLayoutResourceSP windowLayout = rserver->resource("", "", args.windowLayout());
627 if (windowLayout) {
628 windowLayout->applyLayout();
629 }
630 }
631
632 setSplashScreenLoadingText(i18n("Launching..."));
633
634 if (showmainWindow) {
635 d->mainWindow = kisPart->currentMainwindow();
636
637 if (!args.workspace().isEmpty()) {
639 KisWorkspaceResourceSP workspace = rserver->resource("", "", args.workspace());
640 if (workspace) {
641 d->mainWindow->restoreWorkspace(workspace);
642 }
643 }
644
645 if (args.canvasOnly()) {
646 d->mainWindow->viewManager()->switchCanvasOnly(true);
647 }
648
649 if (args.fullScreen()) {
650 d->mainWindow->showFullScreen();
651 }
652 } else {
653 d->mainWindow = kisPart->createMainWindow();
654 }
655 }
656 short int numberOfOpenDocuments = 0; // number of documents open
657
658 // Check for autosave files that can be restored, if we're not running a batch run (test)
659 if (!d->batchRun) {
661 }
662
663 setSplashScreenLoadingText(QString()); // done loading, so clear out label
664 processEvents();
665
666 //configure the unit manager
668 connect(this, &KisApplication::aboutToQuit, &KisSpinBoxUnitManagerFactory::clearUnitManagerBuilder); //ensure the builder is destroyed when the application leave.
669 //the new syntax slot syntax allow to connect to a non q_object static method.
670
671 // Long-press emulation.
675
676 // Xiaomi workaround: their stylus inexplicably inputs page up and down keys
677 // when pressing stylus buttons. This flag causes the Android platform
678 // integration to turn those into right and middle clicks instead.
679#if KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_PAGE_UP_DOWN
680 auto setPageUpDownMouseButtonEmulationWorkaround = [](bool enabled) {
681 QCoreApplication::setKritaAttribute(KRITA_QATTRIBUTE_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_PAGE_UP_DOWN, enabled);
682 };
683 connect(cfgNotifier,
684 &KisConfigNotifier::sigUsePageUpDownMouseButtonEmulationWorkaroundChanged,
685 this,
686 setPageUpDownMouseButtonEmulationWorkaround);
687 setPageUpDownMouseButtonEmulationWorkaround(cfg.usePageUpDownMouseButtonEmulationWorkaround());
688#endif
689
690 // Xiaomi workaround: historic tablet motion events are garbage, they just
691 // connect the actual points that the tablet sampled with a straight line
692 // and no pressure emulation, leading to jagged curves that don't get
693 // smoothed out. This flag disables reading those historic events.
694#if KRITA_QT_HAS_ANDROID_IGNORE_HISTORIC_TABLET_EVENTS
695 auto setIgnoreHistoricTabletEventsWorkaround = [](bool enabled) {
696 QCoreApplication::setKritaAttribute(KRITA_QATTRIBUTE_ANDROID_IGNORE_HISTORIC_TABLET_EVENTS, enabled);
697 };
698 connect(cfgNotifier,
699 &KisConfigNotifier::sigUseIgnoreHistoricTabletEventsWorkaroundChanged,
700 this,
701 setIgnoreHistoricTabletEventsWorkaround);
702 setIgnoreHistoricTabletEventsWorkaround(cfg.usePageUpDownMouseButtonEmulationWorkaround());
703#endif
704
705 // Create a new image, if needed
706 if (doNewImage) {
708 if (doc) {
709 kisPart->addDocument(doc);
710 d->mainWindow->addViewAndNotifyLoadingCompleted(doc);
711 }
712 }
713
714 // Get the command line arguments which we have to parse
715 int argsCount = args.filenames().count();
716 if (argsCount > 0) {
717 // Loop through arguments
718 for (int argNumber = 0; argNumber < argsCount; argNumber++) {
719 QString fileName = args.filenames().at(argNumber);
720 // are we just trying to open a template?
721 if (doTemplate) {
722 // called in mix with batch options? ignore and silently skip
723 if (d->batchRun) {
724 continue;
725 }
726 if (createNewDocFromTemplate(fileName, d->mainWindow)) {
727 ++numberOfOpenDocuments;
728 }
729 // now try to load
730 }
731 else {
732 if (exportAs) {
733 QString outputMimetype = KisMimeDatabase::mimeTypeForFile(exportFileName, false);
734 if (outputMimetype == "application/octetstream") {
735 dbgKrita << i18n("Mimetype not found, try using the -mimetype option") << Qt::endl;
736 return false;
737 }
738
739 KisDocument *doc = kisPart->createDocument();
740 doc->setFileBatchMode(d->batchRun);
741 bool result = doc->openPath(fileName);
742
743 if (!result) {
744 errKrita << "Could not load " << fileName << ":" << doc->errorMessage();
745 QTimer::singleShot(0, this, SLOT(quit()));
746 return false;
747 }
748
749 if (exportFileName.isEmpty()) {
750 errKrita << "Export destination is not specified for" << fileName << "Please specify export destination with --export-filename option";
751 QTimer::singleShot(0, this, SLOT(quit()));
752 return false;
753 }
754
755 qApp->processEvents(); // For vector layers to be updated
756
757 doc->setFileBatchMode(true);
758 doc->image()->waitForDone();
759
760 if (!doc->exportDocumentSync(exportFileName, outputMimetype.toLatin1())) {
761 errKrita << "Could not export " << fileName << "to" << exportFileName << ":" << doc->errorMessage();
762 }
763 QTimer::singleShot(0, this, SLOT(quit()));
764 return true;
765 }
766 else if (exportSequence) {
767 KisDocument *doc = kisPart->createDocument();
768 doc->setFileBatchMode(d->batchRun);
769 doc->openPath(fileName);
770 qApp->processEvents(); // For vector layers to be updated
771
772 if (!doc->image()->animationInterface()->hasAnimation()) {
773 errKrita << "This file has no animation." << Qt::endl;
774 QTimer::singleShot(0, this, SLOT(quit()));
775 return false;
776 }
777
778 doc->setFileBatchMode(true);
779 int sequenceStart = 0;
780
781
782 qDebug() << ppVar(exportFileName);
785 exportFileName,
786 sequenceStart,
787 false,
788 0);
789
790 exporter.setBatchMode(d->batchRun);
791
793 qDebug() << ppVar(result);
794
796 errKrita << i18n("Failed to render animation frames!") << Qt::endl;
797 }
798
799 QTimer::singleShot(0, this, SLOT(quit()));
800 return true;
801 }
802 else if (d->mainWindow) {
803 if (QFileInfo(fileName).fileName().endsWith(".bundle", Qt::CaseInsensitive)) {
804 d->mainWindow->installBundle(fileName);
805 }
806 else {
807 KisMainWindow::OpenFlags flags = d->batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
808
809 if (d->mainWindow->openDocument(fileName, flags)) {
810 // Normal case, success
811 numberOfOpenDocuments++;
812 }
813 }
814 }
815 }
816 }
817 }
818
819 //add an image as file-layer
820 if (!args.fileLayer().isEmpty()){
821 if (d->mainWindow->viewManager()->image()){
822 KisFileLayer *fileLayer = new KisFileLayer(d->mainWindow->viewManager()->image(), "",
823 args.fileLayer(), KisFileLayer::None, "Bicubic",
824 d->mainWindow->viewManager()->image()->nextLayerName(i18n("File layer")), OPACITY_OPAQUE_U8);
825 QFileInfo fi(fileLayer->path());
826 if (fi.exists()){
827 KisNodeCommandsAdapter adapter(d->mainWindow->viewManager());
828 adapter.addNode(fileLayer, d->mainWindow->viewManager()->activeNode()->parent(),
829 d->mainWindow->viewManager()->activeNode());
830 }
831 else{
832 QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "Krita:Warning"),
833 i18n("Cannot add %1 as a file layer: the file does not exist.", fileLayer->path()));
834 }
835 }
836 else if (this->isRunning()){
837 QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "Krita:Warning"),
838 i18n("Cannot add the file layer: no document is open.\n\n"
839"You can create a new document using the --new-image option, or you can open an existing file.\n\n"
840"If you instead want to add the file layer to a document in an already running instance of Krita, check the \"Allow only one instance of Krita\" checkbox in the settings (Settings -> General -> Window)."));
841 }
842 else {
843 QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "Krita: Warning"),
844 i18n("Cannot add the file layer: no document is open.\n"
845 "You can either create a new file using the --new-image option, or you can open an existing file."));
846 }
847 }
848
849 // fixes BUG:369308 - Krita crashing on splash screen when loading.
850 // trying to open a file before Krita has loaded can cause it to hang and crash
851 if (d->splashScreen) {
852 d->splashScreen->displayLinks(true);
853 d->splashScreen->displayRecentFiles(true);
854 }
855
856 Q_FOREACH(const QByteArray &message, d->earlyRemoteArguments) {
857 executeRemoteArguments(message, d->mainWindow);
858 }
859
861
862 // process File open event files
863 if (!d->earlyFileOpenEvents.isEmpty()) {
865 Q_FOREACH(QString fileName, d->earlyFileOpenEvents) {
866 d->mainWindow->openDocument(fileName, QFlags<KisMainWindow::OpenFlag>());
867 }
868 }
869
871
872 // not calling this before since the program will quit there.
873 return true;
874}
875
883
884void KisApplication::setSplashScreen(QWidget *splashScreen)
885{
886 d->splashScreen = qobject_cast<KisSplashScreen*>(splashScreen);
887}
888
889void KisApplication::setSplashScreenLoadingText(const QString &textToLoad)
890{
891 if (d->splashScreen) {
892 d->splashScreen->setLoadingText(textToLoad);
893 d->splashScreen->repaint();
894 }
895}
896
898{
899 if (d->splashScreen) {
900 // hide the splashscreen to see the dialog
901 d->splashScreen->hide();
902 }
903}
904
905
906bool KisApplication::notify(QObject *receiver, QEvent *event)
907{
908 try {
909 bool result = true;
910
916 AppRecursionInfo &info = s_recursionInfo->localData();
917
918 {
919 // QApplication::notify() can throw, so use RAII for counters
920 AppRecursionGuard guard(&info);
921
923
924 if (info.eventRecursionCount > 1) {
926 KIS_SAFE_ASSERT_RECOVER_NOOP(typedEvent->destination == receiver);
927
928 info.postponedSynchronizationEvents.emplace(KisSynchronizedConnectionEvent(*typedEvent));
929 } else {
930 result = QApplication::notify(receiver, event);
931 }
932 } else {
933 result = QApplication::notify(receiver, event);
934 }
935 }
936
937 if (!info.eventRecursionCount) {
939
940 }
941
942 return result;
943
944 } catch (std::exception &e) {
945 qWarning("Error %s sending event %i to object %s",
946 e.what(), event->type(), qPrintable(receiver->objectName()));
947 } catch (...) {
948 qWarning("Error <unknown> sending event %i to object %s",
949 event->type(), qPrintable(receiver->objectName()));
950 }
951 return false;
952}
953
955{
956 AppRecursionInfo &info = s_recursionInfo->localData();
957
958 while (!info.postponedSynchronizationEvents.empty()) {
959 // QApplication::notify() can throw, so use RAII for counters
960 AppRecursionGuard guard(&info);
961
964 KisSynchronizedConnectionEvent typedEvent = info.postponedSynchronizationEvents.front();
965 info.postponedSynchronizationEvents.pop();
966
967 if (!typedEvent.destination) {
968 qWarning() << "WARNING: the destination object of KisSynchronizedConnection has been destroyed during postponed delivery";
969 continue;
970 }
971
972 QApplication::notify(typedEvent.destination, &typedEvent);
973 }
974}
975
977{
978 if (qEnvironmentVariableIsSet("STEAMAPPID") || qEnvironmentVariableIsSet("SteamAppId")) {
979 return true;
980 }
981
982 if (applicationDirPath().toLower().contains("steam")) {
983 return true;
984 }
985
986#ifdef Q_OS_WIN
987 // This is also true for user-installed MSIX, but that's
988 // likely only true in institutional situations, where
989 // we don't want to show the beginning banner either.
991 return true;
992 }
993#endif
994
995#ifdef Q_OS_MACOS
996 KisMacosEntitlements entitlements;
997 if (entitlements.sandbox()) {
998 return true;
999 }
1000#endif
1001
1002 return false;
1003}
1004
1006{
1011#if !defined(HIDE_SAFE_ASSERTS) || defined(CRASH_ON_SAFE_ASSERTS)
1012
1013 auto verifyTypeRegistered = [] (const char *type) {
1014 const int typeId = QMetaType::type(type);
1015
1016 if (typeId <= 0) {
1017 qFatal("ERROR: type-id for metatype %s is not found", type);
1018 }
1019
1020 if (!QMetaType::isRegistered(typeId)) {
1021 qFatal("ERROR: metatype %s is not registered", type);
1022 }
1023 };
1024
1025 verifyTypeRegistered("KisBrushSP");
1026 verifyTypeRegistered("KoSvgText::AutoValue");
1027 verifyTypeRegistered("KoSvgText::BackgroundProperty");
1028 verifyTypeRegistered("KoSvgText::StrokeProperty");
1029 verifyTypeRegistered("KoSvgText::TextTransformInfo");
1030 verifyTypeRegistered("KoSvgText::TextIndentInfo");
1031 verifyTypeRegistered("KoSvgText::TabSizeInfo");
1032 verifyTypeRegistered("KoSvgText::LineHeightInfo");
1033 verifyTypeRegistered("KisPaintopLodLimitations");
1034 verifyTypeRegistered("KisImageSP");
1035 verifyTypeRegistered("KisImageSignalType");
1036 verifyTypeRegistered("KisNodeSP");
1037 verifyTypeRegistered("KisNodeList");
1038 verifyTypeRegistered("KisPaintDeviceSP");
1039 verifyTypeRegistered("KisTimeSpan");
1040 verifyTypeRegistered("KoColor");
1041 verifyTypeRegistered("KoResourceSP");
1042 verifyTypeRegistered("KoResourceCacheInterfaceSP");
1043 verifyTypeRegistered("KisAsyncAnimationRendererBase::CancelReason");
1044 verifyTypeRegistered("KisGridConfig");
1045 verifyTypeRegistered("KisGuidesConfig");
1046 verifyTypeRegistered("KisUpdateInfoSP");
1047 verifyTypeRegistered("KisToolChangesTrackerDataSP");
1048 verifyTypeRegistered("QVector<QImage>");
1049 verifyTypeRegistered("SnapshotDirInfoList");
1050 verifyTypeRegistered("TransformTransactionProperties");
1051 verifyTypeRegistered("ToolTransformArgs");
1052 verifyTypeRegistered("QPainterPath");
1053#endif
1054}
1055
1056void KisApplication::executeRemoteArguments(QByteArray message, KisMainWindow *mainWindow)
1057{
1059 const bool doTemplate = args.doTemplate();
1060 const bool doNewImage = args.doNewImage();
1061 const int argsCount = args.filenames().count();
1062 bool documentCreated = false;
1063
1064 // Create a new image, if needed
1065 if (doNewImage) {
1067 if (doc) {
1069 d->mainWindow->addViewAndNotifyLoadingCompleted(doc);
1070 }
1071 }
1072 if (argsCount > 0) {
1073 // Loop through arguments
1074 for (int argNumber = 0; argNumber < argsCount; ++argNumber) {
1075 QString filename = args.filenames().at(argNumber);
1076 // are we just trying to open a template?
1077 if (doTemplate) {
1078 documentCreated |= createNewDocFromTemplate(filename, mainWindow);
1079 }
1080 else if (QFile(filename).exists()) {
1081 KisMainWindow::OpenFlags flags = d->batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
1082 documentCreated |= mainWindow->openDocument(filename, flags);
1083 }
1084 }
1085 }
1086
1087 //add an image as file-layer if called in another process and singleApplication is enabled
1088 if (!args.fileLayer().isEmpty()){
1089 if (argsCount > 0 && !documentCreated){
1090 //arg was passed but document was not created so don't add the file layer.
1091 QMessageBox::warning(mainWindow, i18nc("@title:window", "Krita:Warning"),
1092 i18n("Couldn't open file %1",args.filenames().at(argsCount - 1)));
1093 }
1094 else if (mainWindow->viewManager()->image()){
1095 KisFileLayer *fileLayer = new KisFileLayer(mainWindow->viewManager()->image(), "",
1096 args.fileLayer(), KisFileLayer::None, "Bicubic",
1097 mainWindow->viewManager()->image()->nextLayerName(i18n("File layer")), OPACITY_OPAQUE_U8);
1098 QFileInfo fi(fileLayer->path());
1099 if (fi.exists()){
1100 KisNodeCommandsAdapter adapter(d->mainWindow->viewManager());
1101 adapter.addNode(fileLayer, d->mainWindow->viewManager()->activeNode()->parent(),
1102 d->mainWindow->viewManager()->activeNode());
1103 }
1104 else{
1105 QMessageBox::warning(mainWindow, i18nc("@title:window", "Krita:Warning"),
1106 i18n("Cannot add %1 as a file layer: the file does not exist.", fileLayer->path()));
1107 }
1108 }
1109 else {
1110 QMessageBox::warning(mainWindow, i18nc("@title:window", "Krita:Warning"),
1111 i18n("Cannot add the file layer: no document is open."));
1112 }
1113 }
1114}
1115
1116
1117void KisApplication::remoteArguments(const QString &message)
1118{
1119 // check if we have any mainwindow
1120 KisMainWindow *mw = qobject_cast<KisMainWindow*>(qApp->activeWindow());
1121
1122 if (!mw && KisPart::instance()->mainWindows().size() > 0) {
1123 mw = KisPart::instance()->mainWindows().first();
1124 }
1125
1126 const QByteArray unpackedMessage =
1127 QByteArray::fromBase64(message.toLatin1());
1128
1129 if (!mw) {
1130 d->earlyRemoteArguments << unpackedMessage;
1131 return;
1132 }
1133 executeRemoteArguments(unpackedMessage, mw);
1134}
1135
1137{
1138 if (!d->mainWindow) {
1139 d->earlyFileOpenEvents.append(url);
1140 return;
1141 }
1142
1143 KisMainWindow::OpenFlags flags = d->batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
1144 d->mainWindow->openDocument(url, flags);
1145}
1146
1147
1149{
1150 if (enabled && !d->longPressEventFilter) {
1151 d->longPressEventFilter = new KisLongPressEventFilter(this);
1152 installEventFilter(d->longPressEventFilter);
1153 } else if (!enabled && d->longPressEventFilter) {
1154 removeEventFilter(d->longPressEventFilter);
1155 d->longPressEventFilter->deleteLater();
1156 d->longPressEventFilter = nullptr;
1157 }
1158}
1159
1161{
1162 if (d->batchRun) return;
1163
1165
1166 // Check for autosave files from a previous run. There can be several, and
1167 // we want to offer a restore for every one. Including a nice thumbnail!
1168
1169 // Hidden autosave files
1170 QStringList filters = QStringList() << QString(".krita-*-*-autosave.kra");
1171
1172 // all autosave files for our application
1173 QStringList autosaveFiles = dir.entryList(filters, QDir::Files | QDir::Hidden);
1174
1175 // Visible autosave files
1176 filters = QStringList() << QString("krita-*-*-autosave.kra");
1177 autosaveFiles += dir.entryList(filters, QDir::Files);
1178
1179 // Allow the user to make their selection
1180 if (autosaveFiles.size() > 0) {
1181 if (d->splashScreen) {
1182 // hide the splashscreen to see the dialog
1183 d->splashScreen->hide();
1184 }
1185 d->autosaveDialog = new KisAutoSaveRecoveryDialog(autosaveFiles, activeWindow());
1186 QDialog::DialogCode result = (QDialog::DialogCode) d->autosaveDialog->exec();
1187
1188 if (result == QDialog::Accepted) {
1189 QStringList filesToRecover = d->autosaveDialog->recoverableFiles();
1190 Q_FOREACH (const QString &autosaveFile, autosaveFiles) {
1191 if (!filesToRecover.contains(autosaveFile)) {
1192 KisUsageLogger::log(QString("Removing autosave file %1").arg(dir.absolutePath() + "/" + autosaveFile));
1193 QFile::remove(dir.absolutePath() + "/" + autosaveFile);
1194 }
1195 }
1196 autosaveFiles = filesToRecover;
1197 } else {
1198 autosaveFiles.clear();
1199 }
1200
1201 if (autosaveFiles.size() > 0) {
1202 QList<QString> autosavePaths;
1203 Q_FOREACH (const QString &autoSaveFile, autosaveFiles) {
1204 const QString path = dir.absolutePath() + QLatin1Char('/') + autoSaveFile;
1205 autosavePaths << path;
1206 }
1207 if (d->mainWindow) {
1208 Q_FOREACH (const QString &path, autosavePaths) {
1209 KisMainWindow::OpenFlags flags = d->batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
1210 d->mainWindow->openDocument(path, flags | KisMainWindow::RecoveryFile);
1211 }
1212 }
1213 }
1214 // cleanup
1215 delete d->autosaveDialog;
1216 d->autosaveDialog = nullptr;
1217 }
1218}
1219
1220bool KisApplication::createNewDocFromTemplate(const QString &fileName, KisMainWindow *mainWindow)
1221{
1222 QString templatePath;
1223
1224 if (QFile::exists(fileName)) {
1225 templatePath = fileName;
1226 dbgUI << "using full path...";
1227 }
1228 else {
1229 QString desktopName(fileName);
1230 const QString templatesResourcePath = QStringLiteral("templates/");
1231
1232 QStringList paths = KoResourcePaths::findAllAssets("data", templatesResourcePath + "*/" + desktopName);
1233 if (paths.isEmpty()) {
1234 paths = KoResourcePaths::findAllAssets("data", templatesResourcePath + desktopName);
1235 }
1236
1237 if (paths.isEmpty()) {
1238 QMessageBox::critical(qApp->activeWindow(), i18nc("@title:window", "Krita"),
1239 i18n("No template found for: %1", desktopName));
1240 } else if (paths.count() > 1) {
1241 QMessageBox::critical(qApp->activeWindow(), i18nc("@title:window", "Krita"),
1242 i18n("Too many templates found for: %1", desktopName));
1243 } else {
1244 templatePath = paths.at(0);
1245 }
1246 }
1247
1248 if (!templatePath.isEmpty()) {
1249 KDesktopFile templateInfo(templatePath);
1250
1251 KisMainWindow::OpenFlags batchFlags = d->batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
1252 if (mainWindow->openDocument(templatePath, KisMainWindow::Import | batchFlags)) {
1253 dbgUI << "Template loaded...";
1254 return true;
1255 }
1256 else {
1257 QMessageBox::critical(qApp->activeWindow(), i18nc("@title:window", "Krita"),
1258 i18n("Template %1 failed to load.", fileName));
1259 }
1260 }
1261
1262 return false;
1263}
1264
1266{
1267 KIS_ASSERT_RECOVER_RETURN(qApp->thread() == QThread::currentThread());
1268
1269 KSharedConfigPtr config = KSharedConfig::openConfig();
1270 config->markAsClean();
1271
1272 // find user settings file
1273 const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
1274 QString kritarcPath = configPath + QStringLiteral("/kritarc");
1275
1276 QFile kritarcFile(kritarcPath);
1277
1278 if (kritarcFile.exists()) {
1279 if (kritarcFile.open(QFile::ReadWrite)) {
1280 QString backupKritarcPath = kritarcPath + QStringLiteral(".backup");
1281
1282 QFile backupKritarcFile(backupKritarcPath);
1283
1284 if (backupKritarcFile.exists()) {
1285 backupKritarcFile.remove();
1286 }
1287
1288 QMessageBox::information(qApp->activeWindow(),
1289 i18nc("@title:window", "Krita"),
1290 i18n("Krita configurations reset!\n\n"
1291 "Backup file was created at: %1\n\n"
1292 "Restart Krita for changes to take effect.",
1293 backupKritarcPath),
1294 QMessageBox::Ok, QMessageBox::Ok);
1295
1296 // clear file
1297 kritarcFile.rename(backupKritarcPath);
1298
1299 kritarcFile.close();
1300 }
1301 else {
1302 QMessageBox::warning(qApp->activeWindow(),
1303 i18nc("@title:window", "Krita"),
1304 i18n("Failed to clear %1\n\n"
1305 "Please make sure no other program is using the file and try again.",
1306 kritarcPath),
1307 QMessageBox::Ok, QMessageBox::Ok);
1308 }
1309 }
1310
1311 // reload from disk; with the user file settings cleared,
1312 // this should load any default configuration files shipping with the program
1313 config->reparseConfiguration();
1314 config->sync();
1315
1316 // Restore to default workspace
1317 KConfigGroup cfg = KSharedConfig::openConfig()->group("MainWindow");
1318
1319 QString currentWorkspace = cfg.readEntry<QString>("CurrentWorkspace", "Default");
1321 KisWorkspaceResourceSP workspace = rserver->resource("", "", currentWorkspace);
1322
1323 if (workspace) {
1324 d->mainWindow->restoreWorkspace(workspace);
1325 }
1326}
1327
1329{
1330 bool ok = QMessageBox::question(qApp->activeWindow(),
1331 i18nc("@title:window", "Krita"),
1332 i18n("Do you want to clear the settings file?"),
1333 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes;
1334 if (ok) {
1335 resetConfig();
1336 }
1337}
1338
1340{
1341 return d->extendedModifiersPluginInterface.data();
1342}
1343
1344#ifdef Q_OS_ANDROID
1345KisAndroidDonations *KisApplication::androidDonations()
1346{
1347 if (!d->androidDonations) {
1348 d->androidDonations = new KisAndroidDonations(this);
1349 d->androidDonations->syncState();
1350 }
1351 return d->androidDonations;
1352}
1353#endif
QList< QString > QStringList
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
const quint8 OPACITY_OPAQUE_U8
void setCurrentTheme(const QString &name)
static KisActionRegistry * instance()
QVector< QByteArray > earlyRemoteArguments
QPointer< KisSplashScreen > splashScreen
QScopedPointer< KisExtendedModifiersMapperPluginInterface > extendedModifiersPluginInterface
QPointer< KisMainWindow > mainWindow
QVector< QString > earlyFileOpenEvents
ResetStarting(KisSplashScreen *splash, int fileCount)
QPointer< KisSplashScreen > m_splash
Base class for the Krita app.
bool notify(QObject *receiver, QEvent *event) override
Overridden to handle exceptions from event handlers.
void setSplashScreenLoadingText(const QString &)
bool event(QEvent *event) override
virtual bool start(const KisApplicationArguments &args)
void remoteArguments(const QString &message)
void executeRemoteArguments(QByteArray message, KisMainWindow *mainWindow)
KisApplication(const QString &key, int &argc, char **argv)
KisExtendedModifiersMapperPluginInterface * extendedModifiersPluginInterface()
void slotSetLongPress(bool enabled)
void setSplashScreen(QWidget *splash)
void fileOpenRequested(const QString &url)
QScopedPointer< Private > d
~KisApplication() override
void initializeGlobals(const KisApplicationArguments &args)
bool createNewDocFromTemplate(const QString &fileName, KisMainWindow *m_mainWindow)
static void verifyMetatypeRegistration()
void processPostponedSynchronizationEvents()
Result regenerateRange(KisViewManager *viewManager) override
start generation of frames and (if not in batch mode) show the dialog
void setBatchMode(bool value)
setting batch mode to true will prevent any dialogs or message boxes from showing on screen....
void sigLongPressChanged(bool enabled)
static KisConfigNotifier * instance()
QString widgetStyle(bool defaultValue=false)
void setCanvasState(const QString &state) const
void writeEntry(const QString &name, const T &value)
Definition kis_config.h:822
SessionOnStartup sessionOnStartup(bool defaultValue=false) const
bool longPressEnabled(bool defaultValue=false) const
T readEntry(const QString &name, const T &defaultValue=T())
Definition kis_config.h:832
QString canvasState(bool defaultValue=false) const
@ SOS_PreviousSession
Definition kis_config.h:371
@ SOS_ShowSessionManager
Definition kis_config.h:372
void setFileBatchMode(const bool batchMode)
KisImageSP image
QString errorMessage() const
bool exportDocumentSync(const QString &path, const QByteArray &mimeType, KisPropertiesConfigurationSP exportConfiguration=0)
bool openPath(const QString &path, OpenFlags flags=None)
openPath Open a Path
The KisFileLayer class loads a particular file as a layer into the layer stack.
QString path() const
static KisFilterRegistry * instance()
static KisGeneratorRegistry * instance()
const KisTimeSpan & documentPlaybackRange() const
documentPlaybackRange
void waitForDone()
KisImageAnimationInterface * animationInterface() const
QString nextLayerName(const QString &baseName="") const
Definition kis_image.cc:715
Main window for Krita.
bool openDocument(const QString &path, OpenFlags flags)
KisViewManager * viewManager
static KisMetadataBackendRegistry * instance()
static QString mimeTypeForFile(const QString &file, bool checkExistingFiles=true)
Find the mimetype for the given filename. The filename must include a suffix.
static QString mimeTypeForSuffix(const QString &suffix)
Find the mimetype for a given extension. The extension may have the form "*.xxx" or "xxx".
void addNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis, KisImageLayerAddCommand::Flags flags=KisImageLayerAddCommand::DoRedoUpdates|KisImageLayerAddCommand::DoUndoUpdates)
static KisPaintOpRegistry * instance()
QList< QPointer< KisMainWindow > > mainWindows
Definition KisPart.cpp:107
static KisPart * instance()
Definition KisPart.cpp:131
bool restoreSession(const QString &sessionName)
Definition KisPart.cpp:644
void addDocument(KisDocument *document, bool notify=true)
Definition KisPart.cpp:211
KisMainWindow * currentMainwindow() const
Definition KisPart.cpp:459
void startBlankSession()
Definition KisPart.cpp:636
KisDocument * createDocument() const
Definition KisPart.cpp:230
void showSessionManager()
Definition KisPart.cpp:626
KisMainWindow * createMainWindow(QUuid id=QUuid())
Definition KisPart.cpp:260
static KisPlatformPluginInterfaceFactory * instance()
static void performHouseKeepingOnExit()
perform optimize and vacuum when necessary
static void deleteTemporaryResources()
Delete all storages that are Unknown or Memory and all resources that are marked temporary or belong ...
static bool initialize(const QString &location)
initializes the database and updates the scheme if necessary. Does not actually fill the database wit...
static QString lastError()
lastError returns the last SQL error.
The KisResourceLoaderRegistry class manages the loader plugins for resources. Every resource can be l...
static KisResourceLoaderRegistry * instance()
void registerFixup(int priority, ResourceCacheFixup *fixup)
LocatorError initialize(const QString &installationResourcesLocation)
initialize Setup the resource locator for use.
static KisResourceLocator * instance()
static KisResourceServerProvider * instance()
KoResourceServer< KisWorkspaceResource > * workspaceServer()
KoResourceServer< KisWindowLayoutResource > * windowLayoutServer()
static KisSRGBSurfaceColorSpaceManager * tryCreateForCurrentPlatform(QWidget *widget)
static void setDefaultUnitManagerBuilder(KisSpinBoxUnitManagerBuilder *pBuilder)
set a builder the factory can use. The factory should take on the lifecycle of the builder,...
static void registerSynchronizedEventBarrier(std::function< void()> callback)
static void log(const QString &message)
Logs with date/time.
static QString screenInformation()
Returns information about all available screens.
static void writeSysInfo(const QString &message)
Writes to the system information file and Krita log.
KisImageWSP image() const
Return the image this view is displaying.
static KoDockRegistry * instance()
static QString getAppDataLocation()
static void addAssetType(const QString &type, const char *basetype, const QString &relativeName, bool priority=true)
static QString getApplicationRoot()
static QStringList findAllAssets(const QString &type, const QString &filter=QString(), SearchOptions options=NoSearchOptions)
static QString saveLocation(const QString &type, const QString &suffix=QString(), bool create=true)
QSharedPointer< T > resource(const QString &md5, const QString &fileName, const QString &name)
resource retrieves a resource. If the md5sum is not empty, the resource will only be retrieved if a r...
static KoShapeRegistry * instance()
static KoToolRegistry * instance()
The QtSingleApplication class provides an API to detect and communicate with running instances of an ...
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
#define dbgKrita
Definition kis_debug.h:45
#define errKrita
Definition kis_debug.h:107
#define dbgUI
Definition kis_debug.h:52
#define ppVar(var)
Definition kis_debug.h:155
constexpr const char * currentUnderlyingStyleNameProperty
Definition kis_global.h:116
QIcon loadIcon(const QString &name)
KRITAVERSION_EXPORT QString versionString(bool checkGit=false)
const QString GbrBrushes
const QString PngBrushes
const QString GihBrushes
const QString SvgBrushes
const QString StopGradients
const QString KritaPaintOpPresets
const QString SegmentedGradients
const QString Palettes
const QString Symbols
const QString FontFamilies
const QString CssStyles
const QString LayerStyles
const QString Brushes
const QString GamutMasks
const QString Patterns
const QString SeExprScripts
const QString Gradients
const QString Workspaces
const QString WindowLayouts
const QString Sessions
const QString PaintOpPresets
void setMouseCoalescingEnabled(bool enabled)
Definition osx.mm:17
static KisApplicationArguments deserialize(QByteArray &serialized)
KisDocument * createDocumentFromArguments() const
KisNodeWSP parent
Definition kis_node.cpp:86
Event type used for synchronizing connection in KisSynchronizedConnection.
static KoColorSpaceRegistry * instance()