Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_dlg_preferences.cc
Go to the documentation of this file.
1/*
2 * preferencesdlg.cc - part of KImageShop
3 *
4 * SPDX-FileCopyrightText: 1999 Michael Koch <koch@kde.org>
5 * SPDX-FileCopyrightText: 2003-2011 Boudewijn Rempt <boud@valdyas.org>
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10#include "kis_dlg_preferences.h"
11
12#include <config-hdr.h>
13#include <opengl/kis_opengl.h>
14
15#include <QBitmap>
16#include <QCheckBox>
17#include <QComboBox>
18#include <QClipboard>
19#include <QCursor>
20#include <QScreen>
21#include <QFileDialog>
22#include <QFormLayout>
23#include <QGridLayout>
24#include <QGroupBox>
25#include <QLabel>
26#include <QLayout>
27#include <QLineEdit>
28#include <QMdiArea>
29#include <QMessageBox>
30#include <QPushButton>
31#include <QRadioButton>
32#include <QSettings>
33#include <QSlider>
34#include <QStandardPaths>
35#include <QThread>
36#include <QStyleFactory>
37#include <QScreen>
38#include <QFontComboBox>
39#include <QFont>
40#include <QSurfaceFormat>
41#include <QColorSpace>
42#include <QTextBrowser>
43
44#include <KisApplication.h>
45#include <KisDocument.h>
46#include <kis_icon.h>
47#include <KisPart.h>
50#include <KoColorProfile.h>
51#include <KoColorSpaceEngine.h>
52#include <KoConfigAuthorPage.h>
53#include <KoConfig.h>
54#include <KoPointerEvent.h>
55
56#include <KoFileDialog.h>
58#include "KoID.h"
59#include <KoVBox.h>
60
61#include <KTitleWidget>
62#include <KoResourcePaths.h>
63#include <kformat.h>
64#include <klocalizedstring.h>
65#include <kstandardguiitem.h>
66#include <kundo2stack.h>
67
68#include <KisResourceCacheDb.h>
69#include <KisResourceLocator.h>
70
74#include "kis_action_registry.h"
75#include <kis_image.h>
76#include <KisSqueezedComboBox.h>
78#include "kis_clipboard.h"
80#include "KoColorSpace.h"
83#include "kis_color_manager.h"
84#include "kis_config.h"
85#include "kis_image_config.h"
87#include "KisMainWindow.h"
88#include "KisMimeDatabase.h"
93#ifdef Q_OS_LINUX
94#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
96
97#endif
98#include <KoColorimetryUtils.h>
99#endif
100
102
103// for the performance update
104#include <kis_cubic_curve.h>
105#include <kis_signals_blocker.h>
106
109
111#include <config-qt-patches-present.h>
112
113#ifdef Q_OS_WIN
114#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
115// this include is Qt5-only, the switch to WinTab is embedded in Qt
116# include "config_qt5_has_wintab_switch.h"
117#else
118# include <QtGui/private/qguiapplication_p.h>
119# include <QtGui/qpa/qplatformintegration.h>
120#endif
121#include "config-high-dpi-scale-factor-rounding-policy.h"
123#endif
124
130Q_GUI_EXPORT int qt_defaultDpi();
131
132QString shortNameOfDisplay(int index)
133{
134 if (QGuiApplication::screens().length() <= index) {
135 return QString();
136 }
137 QScreen* screen = QGuiApplication::screens()[index];
138 QString resolution = QString::number(screen->geometry().width()).append("x").append(QString::number(screen->geometry().height()));
139 QString name = screen->name();
140 // name and resolution for a specific screen can change, so they are not used in the identifier; but they can help people understand which screen is which
141
142 KisConfig cfg(true);
143 QString shortName = resolution + " " + name + " " + cfg.getScreenStringIdentfier(index);
144 return shortName;
145}
146
147
148struct WritableLocationValidator : public QValidator {
150 : QValidator(parent)
151 {
152 }
153
154 State validate(QString &line, int &/*pos*/) const override
155 {
156 QFileInfo fi(line);
157 if (!fi.isWritable()) {
158 return Intermediate;
159 }
160 return Acceptable;
161 }
162};
163
164struct BackupSuffixValidator : public QValidator {
165 BackupSuffixValidator(QObject *parent)
166 : QValidator(parent)
168 << "0" << "1" << "2" << "3" << "4" << "5" << "6" << "7" << "8" << "9"
169 << "/" << "\\" << ":" << ";" << " ")
170 {}
171
173
175
176 State validate(QString &line, int &/*pos*/) const override
177 {
178 Q_FOREACH(const QString invalidChar, invalidCharacters) {
179 if (line.contains(invalidChar)) {
180 return Invalid;
181 }
182 }
183 return Acceptable;
184 }
185};
186
187/*
188 * We need this because the final item in the ComboBox is a used as an action to launch file selection dialog.
189 * So disabling it makes sure that user doesn't accidentally scroll and select it and get confused why the
190 * file picker launched.
191 */
192class UnscrollableComboBox : public QObject
193{
194public:
195 UnscrollableComboBox(QObject *parent)
196 : QObject(parent)
197 {
198 }
199
200 bool eventFilter(QObject *, QEvent *event) override
201 {
202 if (event->type() == QEvent::Wheel) {
203 event->accept();
204 return true;
205 }
206 return false;
207 }
208};
209
210QIcon addDisabledStatesToIcon(const QIcon &_icon, const QSize &size) {
211
212 QIcon icon = _icon;
213 QImage imageOrig = _icon.pixmap(size).toImage();
214
215 auto makeFainter = [imageOrig] (int alphaVal) {
216 QImage image = imageOrig;
217 QImage alpha = QImage(image.size(), QImage::Format_Alpha8);
218 alpha.fill(alphaVal);
219 image.setAlphaChannel(alpha);
220 QPixmap pixmap = QPixmap();
221 pixmap.convertFromImage(image);
222 return pixmap;
223 };
224
225 QPixmap thirdOpaque = makeFainter(int(256*0.3));
226 QPixmap halfOpaque = makeFainter(int(256*0.65));
227
228 icon.addPixmap(thirdOpaque, QIcon::Mode::Disabled, QIcon::State::Off);
229 icon.addPixmap(thirdOpaque, QIcon::Mode::Disabled, QIcon::State::On);
230 icon.addPixmap(halfOpaque, QIcon::Mode::Normal, QIcon::State::Off);
231
232 return icon;
233}
234
235GeneralTab::GeneralTab(QWidget *_parent, const char *_name)
236 : WdgGeneralSettings(_parent, _name)
237{
238 KisConfig cfg(true);
239
240 // HACK ALERT!
241 // QScrollArea contents are opaque at multiple levels
242 // The contents themselves AND the viewport widget
243 {
244 scrollAreaWidgetContents->setAutoFillBackground(false);
245 scrollAreaWidgetContents->parentWidget()->setAutoFillBackground(false);
246 }
247
248 //
249 // Cursor Tab
250 //
251
252 QStringList cursorItems = QStringList()
253 << i18n("No Cursor")
254 << i18n("Tool Icon")
255 << i18n("Arrow")
256 << i18n("Small Circle")
257 << i18n("Crosshair")
258 << i18n("Triangle Righthanded")
259 << i18n("Triangle Lefthanded")
260 << i18n("Black Pixel")
261 << i18n("White Pixel");
262
263 QStringList outlineItems = QStringList()
264 << i18nc("Display options label to not DISPLAY brush outline", "No Outline")
265 << i18n("Circle Outline")
266 << i18n("Preview Outline")
267 << i18n("Tilt Outline");
268
269 // brush
270
271 m_cmbCursorShape->addItems(cursorItems);
272
273 m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle());
274
275 m_cmbOutlineShape->addItems(outlineItems);
276
277 m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle());
278
279 m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting());
280 m_changeBrushOutline->setChecked(!cfg.forceAlwaysFullSizedOutline());
281
282 KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8());
283 cursorColor.fromQColor(cfg.getCursorMainColor());
284 cursorColorButton->setColor(cursorColor);
285
286 // eraser
287
288 m_chkSeparateEraserCursor->setChecked(cfg.separateEraserCursor());
289
290 m_cmbEraserCursorShape->addItems(cursorItems);
291 m_cmbEraserCursorShape->addItem(i18n("Eraser"));
292
293 m_cmbEraserCursorShape->setCurrentIndex(cfg.eraserCursorStyle());
294
295 m_cmbEraserOutlineShape->addItems(outlineItems);
296
297 m_cmbEraserOutlineShape->setCurrentIndex(cfg.eraserOutlineStyle());
298
299 m_showEraserOutlinePainting->setChecked(cfg.showEraserOutlineWhilePainting());
300 m_changeEraserBrushOutline->setChecked(!cfg.forceAlwaysFullSizedEraserOutline());
301
302 KoColor eraserCursorColor(KoColorSpaceRegistry::instance()->rgb8());
303 eraserCursorColor.fromQColor(cfg.getEraserCursorMainColor());
304 eraserCursorColorButton->setColor(eraserCursorColor);
305
306 // Color sampler
307
308 setColorSamplerPreviewStyleItems(m_cmbColorSamplerPreviewStyle);
309 setColorSamplerPreviewStyleIndexByValue(m_cmbColorSamplerPreviewStyle, cfg.colorSamplerPreviewStyle());
310 connect(m_cmbColorSamplerPreviewStyle,
311 QOverload<int>::of(&QComboBox::currentIndexChanged),
312 this,
314 colorSamplePreviewStyleChanged(m_cmbColorSamplerPreviewStyle->currentIndex());
315
316 m_nmbColorSamplerPreviewSize->setRange(1, 400);
317 m_nmbColorSamplerPreviewSize->setValue(cfg.colorSamplerPreviewCircleDiameter());
318 m_lblColorSamplerPreviewSizePreview->setDiameter(cfg.colorSamplerPreviewCircleDiameter());
319 connect(m_nmbColorSamplerPreviewSize,SIGNAL(valueChanged(int)), SLOT(colorSamplePreviewSizeChanged(int)));
320
321 m_ssbColorSamplerPreviewThickness->setRange(1, 50);
322 m_ssbColorSamplerPreviewThickness->setValue(cfg.colorSamplerPreviewCircleThickness());
323 m_lblColorSamplerPreviewSizePreview->setThickness(cfg.colorSamplerPreviewCircleThickness()/100.0);
324 connect(m_ssbColorSamplerPreviewThickness,SIGNAL(valueChanged(qreal)), SLOT(colorSamplePreviewThicknessChanged(qreal)));
325
326 m_chkColorSamplerPreviewOutlineEnabled->setChecked(cfg.colorSamplerPreviewCircleOutlineEnabled());
327 m_lblColorSamplerPreviewSizePreview->setOutlineEnabled(cfg.colorSamplerPreviewCircleOutlineEnabled());
328 connect(m_chkColorSamplerPreviewOutlineEnabled,SIGNAL(stateChanged(int)), SLOT(colorSamplePreviewOutlineEnabledChanged(int)));
329
330 m_chkColorSamplerPreviewExtraCircles->setChecked(cfg.colorSamplerPreviewCircleExtraCirclesEnabled());
331
332
333 KisSpinBoxI18nHelper::setText(m_ssbColorSamplerPreviewThickness, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
334
335
336
337
338
339
340
341
342 //
343 // Window Tab
344 //
345 chkUseCustomFont->setChecked(cfg.readEntry<bool>("use_custom_system_font", false));
346 cmbCustomFont->findChild <QComboBox*>("stylesComboBox")->setVisible(false);
347
348 QString fontName = cfg.readEntry<QString>("custom_system_font", "");
349 if (fontName.isEmpty()) {
350 cmbCustomFont->setCurrentFont(qApp->font());
351
352 }
353 else {
354 int pointSize = qApp->font().pointSize();
355 cmbCustomFont->setCurrentFont(QFont(fontName, pointSize));
356 }
357 int fontSize = cfg.readEntry<int>("custom_font_size", -1);
358 if (fontSize < 0) {
359 intFontSize->setValue(qApp->font().pointSize());
360 }
361 else {
362 intFontSize->setValue(fontSize);
363 }
364
365 m_cmbMDIType->setCurrentIndex(cfg.readEntry<int>("mdi_viewmode", (int)QMdiArea::TabbedView));
366 enableSubWindowOptions(m_cmbMDIType->currentIndex());
367 connect(m_cmbMDIType, SIGNAL(currentIndexChanged(int)), SLOT(enableSubWindowOptions(int)));
368
369 m_backgroundimage->setText(cfg.getMDIBackgroundImage());
370 connect(m_bnFileName, SIGNAL(clicked()), SLOT(getBackgroundImage()));
371 connect(clearBgImageButton, SIGNAL(clicked()), SLOT(clearBackgroundImage()));
372
373 QString xml = cfg.getMDIBackgroundColor();
374 KoColor mdiColor = KoColor::fromXML(xml);
375 m_mdiColor->setColor(mdiColor);
376
377 m_chkRubberBand->setChecked(cfg.readEntry<int>("mdi_rubberband", cfg.useOpenGL()));
378
379 m_chkCanvasMessages->setChecked(cfg.showCanvasMessages());
380
381 const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
382 QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
383 m_chkHiDPI->setChecked(kritarc.value("EnableHiDPI", true).toBool());
384#if defined(Q_OS_WIN) && defined(HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY)
385 m_chkHiDPIFractionalScaling->setChecked(kritarc.value("EnableHiDPIFractionalScaling", false).toBool());
386#else
387 m_wdgHiDPIFractionalScaling->setEnabled(false);
388#endif
389 chkUsageLogging->setChecked(kritarc.value("LogUsage", true).toBool());
390
391
392 //
393 // Tools tab
394 //
395 m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker());
396 cmbFlowMode->setCurrentIndex((int)!cfg.readEntry<bool>("useCreamyAlphaDarken", true));
397 cmbCmykBlendingMode->setCurrentIndex((int)!cfg.readEntry<bool>("useSubtractiveBlendingForCmykColorSpaces", true));
398 m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt());
399 cmbTouchPainting->addItem(
400 KoPointerEvent::tabletInputReceived() ? i18nc("touch painting", "Auto (Disabled)")
401 : i18nc("touch painting", "Auto (Enabled)"));
402 cmbTouchPainting->addItem(i18nc("touch painting", "Enabled"));
403 cmbTouchPainting->addItem(i18nc("touch painting", "Disabled"));
404 cmbTouchPainting->setCurrentIndex(int(cfg.touchPainting()));
405 chkTouchPressureSensitivity->setChecked(cfg.readEntry("useTouchPressureSensitivity", true));
406 connect(cmbTouchPainting, SIGNAL(currentIndexChanged(int)),
408 updateTouchPressureSensitivityEnabled(cmbTouchPainting->currentIndex());
409
410 chkEnableTransformToolAfterPaste->setChecked(cfg.activateTransformToolAfterPaste());
411 chkZoomHorizontally->setChecked(cfg.zoomHorizontal());
412
413 chkEnableLongPress->setChecked(cfg.longPressEnabled());
414
415 m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled());
416
417 m_cmbKineticScrollingGesture->addItem(i18n("On Touch Drag"));
418 m_cmbKineticScrollingGesture->addItem(i18n("On Click Drag"));
419 m_cmbKineticScrollingGesture->addItem(i18n("On Middle-Click Drag"));
420 //m_cmbKineticScrollingGesture->addItem(i18n("On Right Click Drag"));
421
422 spnZoomSteps->setValue(cfg.zoomSteps());
423
424
425 m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture());
426 m_kineticScrollingSensitivitySlider->setRange(0, 100);
427 m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity());
428 m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars());
429
430 intZoomMarginSize->setValue(cfg.zoomMarginSize());
431
432 bool sapEnabled = cfg.selectionActionBar();
433
434 chkEnableSelectionActionBar->setChecked(sapEnabled);
435
436 //
437 // File handling
438 //
439 int autosaveInterval = cfg.autoSaveInterval();
440 //convert to minutes
441 m_autosaveSpinBox->setValue(autosaveInterval / 60);
442 m_autosaveCheckBox->setChecked(autosaveInterval > 0);
443 chkHideAutosaveFiles->setChecked(cfg.readEntry<bool>("autosavefileshidden", true));
444
445 m_chkCompressKra->setChecked(cfg.compressKra());
446 chkZip64->setChecked(cfg.useZip64());
447 m_chkTrimKra->setChecked(cfg.trimKra());
448 m_chkTrimFramesImport->setChecked(cfg.trimFramesImport());
449
450 m_backupFileCheckBox->setChecked(cfg.backupFile());
451 cmbBackupFileLocation->setCurrentIndex(cfg.readEntry<int>("backupfilelocation", 0));
452 txtBackupFileSuffix->setText(cfg.readEntry<QString>("backupfilesuffix", "~"));
453 QValidator *validator = new BackupSuffixValidator(txtBackupFileSuffix);
454 txtBackupFileSuffix->setValidator(validator);
455 intNumBackupFiles->setValue(cfg.readEntry<int>("numberofbackupfiles", 1));
456
457 cmbDefaultExportFileType->clear();
459
460 QMap<QString, QString> mimeTypeMap;
461
462 foreach (const QString &mimeType, mimeFilter) {
463 QString description = KisMimeDatabase::descriptionForMimeType(mimeType);
464 mimeTypeMap.insert(description, mimeType);
465 }
466
467 // Sort after we get the description because mimeType values have image, application, etc... in front
468 QStringList sortedDescriptions = mimeTypeMap.keys();
469 sortedDescriptions.sort(Qt::CaseInsensitive);
470
471 cmbDefaultExportFileType->addItem(i18n("All Supported Files"), "all/mime");
472 foreach (const QString &description, sortedDescriptions) {
473 const QString &mimeType = mimeTypeMap.value(description);
474 cmbDefaultExportFileType->addItem(description, mimeType);
475 }
476
477 const QString mimeTypeToFind = cfg.exportMimeType(false).toUtf8();
478 const int index = cmbDefaultExportFileType->findData(mimeTypeToFind);
479
480 if (index >= 0) {
481 cmbDefaultExportFileType->setCurrentIndex(index);
482 } else {
483 // Index can't be found, default set to image/png
484 const QString defaultMimeType = "image/png";
485 const int defaultIndex = cmbDefaultExportFileType->findData(defaultMimeType);
486 if (defaultIndex >= 0) {
487 cmbDefaultExportFileType->setCurrentIndex(defaultIndex);
488 } else {
489 // Case where the default mime type is also not found in the combo box
490 qDebug() << "Default mime type not found in the combo box.";
491 }
492 }
493
494 QString selectedMimeType = cmbDefaultExportFileType->currentData().toString();
495
496 //
497 // Animation tab
498 //
499 m_chkAutoPin->setChecked(cfg.autoPinLayersToTimeline());
500 m_chkAdaptivePlaybackRange->setChecked(cfg.adaptivePlaybackRange());
501 m_chkAutoZoom->setChecked(cfg.autoZoomTimelineToPlaybackRange());
502
503 //
504 // Miscellaneous tab
505 //
506 cmbStartupSession->addItem(i18n("Open default window"));
507 cmbStartupSession->addItem(i18n("Load previous session"));
508 cmbStartupSession->addItem(i18n("Show session manager"));
509 cmbStartupSession->setCurrentIndex(cfg.sessionOnStartup());
510
511 chkSaveSessionOnQuit->setChecked(cfg.saveSessionOnQuit(false));
512
513 m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport());
514
515 m_undoStackSize->setValue(cfg.undoStackLimit());
516 chkCumulativeUndo->setChecked(cfg.useCumulativeUndoRedo());
517 connect(chkCumulativeUndo, SIGNAL(toggled(bool)), btnAdvancedCumulativeUndo, SLOT(setEnabled(bool)));
518 btnAdvancedCumulativeUndo->setEnabled(chkCumulativeUndo->isChecked());
519 connect(btnAdvancedCumulativeUndo, SIGNAL(clicked()), SLOT(showAdvancedCumulativeUndoSettings()));
521
522 chkShowRootLayer->setChecked(cfg.showRootLayer());
523
524 chkRenameMergedLayers->setChecked(KisImageConfig(true).renameMergedLayers());
525 chkRenamePastedLayers->setChecked(cfg.renamePastedLayers());
526 chkRenameDuplicatedLayers->setChecked(KisImageConfig(true).renameDuplicatedLayers());
527
528 KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs");
529 bool dontUseNative = true;
530#ifdef Q_OS_ANDROID
531 dontUseNative = false;
532#endif
533#ifdef Q_OS_UNIX
534 if (qgetenv("XDG_CURRENT_DESKTOP") == "KDE") {
535 dontUseNative = false;
536 }
537#endif
538#ifdef Q_OS_MACOS
539 dontUseNative = false;
540#endif
541#ifdef Q_OS_WIN
542 dontUseNative = false;
543#endif
544 m_chkNativeFileDialog->setChecked(!group.readEntry("DontUseNativeFileDialog", dontUseNative));
545
546 if (!qEnvironmentVariable("APPIMAGE").isEmpty()) {
547 // AppImages don't have access to platform plugins. BUG: 447805
548 // Setting the checkbox to false is
549 m_chkNativeFileDialog->setChecked(false);
550 m_chkNativeFileDialog->setEnabled(false);
551 }
552
553 intMaxBrushSize->setValue(KisImageConfig(true).maxBrushSize());
554 chkIgnoreHighFunctionKeys->setChecked(cfg.ignoreHighFunctionKeys());
555#ifndef Q_OS_WIN
556 // we properly support ignoring high F-keys on Windows only. To support on other platforms
557 // we should synchronize KisExtendedModifiersMatcher to ignore the keys as well.
558 chkIgnoreHighFunctionKeys->setVisible(false);
559#endif
560
561 //
562 // Resources
563 //
564 m_urlResourceFolder->setMode(KoFileDialog::OpenDirectory);
565 m_urlResourceFolder->setConfigurationName("resource_directory");
566 const QString resourceLocation = KoResourcePaths::getAppDataLocation();
567 if (QFileInfo(resourceLocation).isWritable()) {
568 m_urlResourceFolder->setFileName(resourceLocation);
569 }
570 else {
571 m_urlResourceFolder->setFileName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
572 }
573 QValidator *writableValidator = new WritableLocationValidator(m_urlResourceFolder);
574 m_urlResourceFolder->setValidator(writableValidator);
575 connect(m_urlResourceFolder, SIGNAL(textChanged(QString)), SLOT(checkResourcePath()));
577
578 grpRestartMessage->setPixmap(
579 grpRestartMessage->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
580 grpRestartMessage->setText(i18n("You will need to Restart Krita for the changes to take an effect."));
581
582 grpAndroidWarningMessage->setVisible(false);
583 grpAndroidWarningMessage->setPixmap(
584 grpAndroidWarningMessage->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
585 grpAndroidWarningMessage->setText(
586 i18n("Saving at a Location picked from the File Picker may slow down the startup!"));
587
588#ifdef Q_OS_ANDROID
589 m_urlResourceFolder->setVisible(false);
590
591 m_resourceFolderSelector->setVisible(true);
592 m_resourceFolderSelector->installEventFilter(new UnscrollableComboBox(this));
593
594 const QList<QPair<QString, QString>> writableLocations = []() {
595 QList<QPair<QString, QString>> writableLocationsAndText;
596 // filters out the duplicates
597 const QList<QString> locations = []() {
598 QStringList filteredLocations;
599 const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
600 Q_FOREACH(const QString &location, locations) {
601 if (!filteredLocations.contains(location)) {
602 filteredLocations.append(location);
603 }
604 }
605 return filteredLocations;
606 }();
607
608 bool isFirst = true;
609
610 Q_FOREACH (QString location, locations) {
611 QString text;
612 QFileInfo fileLocation(location);
613 // The first one that we get from is the "Default"
614 if (isFirst) {
615 text = i18n("Default");
616 isFirst = false;
617 } else if (location.startsWith("/data")) {
618 text = i18n("Internal Storage");
619 } else {
620 text = i18n("SD-Card");
621 }
622 if (fileLocation.isWritable()) {
623 writableLocationsAndText.append({text, location});
624 }
625 }
626 return writableLocationsAndText;
627 }();
628
629 for (auto it = writableLocations.constBegin(); it != writableLocations.constEnd(); ++it) {
630 m_resourceFolderSelector->addItem(it->first + " - " + it->second);
631 // we need it to extract out the path
632 m_resourceFolderSelector->setItemData(m_resourceFolderSelector->count() - 1, it->second, Qt::UserRole);
633 }
634
635 // if the user has selected a custom location, we add it to the list as well.
636 if (resourceLocation.startsWith("content://")) {
637 m_resourceFolderSelector->addItem(resourceLocation);
638 int index = m_resourceFolderSelector->count() - 1;
639 m_resourceFolderSelector->setItemData(index, resourceLocation, Qt::UserRole);
640 m_resourceFolderSelector->setCurrentIndex(index);
641 grpAndroidWarningMessage->setVisible(true);
642 } else {
643 // find the index of the current resource location in the writableLocation, so we can set our view to that
644 auto iterator = std::find_if(writableLocations.constBegin(),
645 writableLocations.constEnd(),
646 [&resourceLocation](QPair<QString, QString> location) {
647 return location.second == resourceLocation;
648 });
649
650 if (iterator != writableLocations.constEnd()) {
651 int index = writableLocations.indexOf(*iterator);
652 KIS_SAFE_ASSERT_RECOVER_NOOP(index < m_resourceFolderSelector->count());
653 m_resourceFolderSelector->setCurrentIndex(index);
654 }
655 }
656
657 // this should be the last item we add.
658 m_resourceFolderSelector->addItem(i18n("Choose Manually"));
659
660 connect(m_resourceFolderSelector, qOverload<int>(&QComboBox::activated), [this](int index) {
661 const int previousIndex = m_resourceFolderSelector->currentIndex();
662
663 // if it is the last item in the last item, then open file picker and set the name returned as the filename
664 if (m_resourceFolderSelector->count() - 1 == index) {
665 KoFileDialog dialog(this, KoFileDialog::OpenDirectory, "Select Directory");
666 const QString selectedDirectory = dialog.filename();
667
668 if (!selectedDirectory.isEmpty()) {
669 // if the index above "Choose Manually" is a content Uri, then we just modify it, and then set that as
670 // the index.
671 if (m_resourceFolderSelector->itemData(index - 1, Qt::DisplayRole)
672 .value<QString>()
673 .startsWith("content://")) {
674 m_resourceFolderSelector->setItemText(index - 1, selectedDirectory);
675 m_resourceFolderSelector->setItemData(index - 1, selectedDirectory, Qt::UserRole);
676 m_resourceFolderSelector->setCurrentIndex(index - 1);
677 } else {
678 // There isn't any content Uri in the ComboBox list, so just insert one, and set that as the index.
679 m_resourceFolderSelector->insertItem(index, selectedDirectory);
680 m_resourceFolderSelector->setItemData(index, selectedDirectory, Qt::UserRole);
681 m_resourceFolderSelector->setCurrentIndex(index);
682 }
683 // since we have selected the custom location, make the warning visible.
684 grpAndroidWarningMessage->setVisible(true);
685 } else {
686 m_resourceFolderSelector->setCurrentIndex(previousIndex);
687 }
688 }
689
690 // hide-unhide based on the selection of user.
691 grpAndroidWarningMessage->setVisible(
692 m_resourceFolderSelector->currentData(Qt::UserRole).value<QString>().startsWith("content://"));
693 });
694
695#else
696 m_resourceFolderSelector->setVisible(false);
697#endif
698
699 grpWindowsAppData->setVisible(false);
700#ifdef Q_OS_WIN
701 QString folderInStandardAppData;
702 QString folderInPrivateAppData;
703 KoResourcePaths::getAllUserResourceFoldersLocationsForWindowsStore(folderInStandardAppData, folderInPrivateAppData);
704
705 if (!folderInPrivateAppData.isEmpty()) {
706 const auto pathToDisplay = [](const QString &path) {
707 // Due to how Unicode word wrapping works, the string does not
708 // wrap after backslashes in Qt 5.12. We don't want the path to
709 // become too long, so we add a U+200B ZERO WIDTH SPACE to allow
710 // wrapping. The downside is that we cannot let the user select
711 // and copy the path because it now contains invisible unicode
712 // code points.
713 // See: https://bugreports.qt.io/browse/QTBUG-80892
714 return QDir::toNativeSeparators(path).replace(QChar('\\'), QStringLiteral(u"\\\u200B"));
715 };
716
717 const QDir privateResourceDir(folderInPrivateAppData);
718 const QDir appDataDir(folderInStandardAppData);
719 grpWindowsAppData->setPixmap(
720 grpWindowsAppData->style()->standardIcon(QStyle::SP_MessageBoxInformation).pixmap(QSize(32, 32)));
721 // Similar text is also used in KisViewManager.cpp
722 grpWindowsAppData->setText(i18nc("@info resource folder",
723 "<p>You are using the Microsoft Store package version of Krita. "
724 "Even though Krita can be configured to place resources under the "
725 "user AppData location, Windows may actually store the files "
726 "inside a private app location.</p>\n"
727 "<p>You should check both locations to determine where "
728 "the files are located.</p>\n"
729 "<p><b>User AppData</b> (<a href=\"copyuser\">Copy</a>):<br/>\n"
730 "%1</p>\n"
731 "<p><b>Private app location</b> (<a href=\"copyprivate\">Copy</a>):<br/>\n"
732 "%2</p>",
733 pathToDisplay(appDataDir.absolutePath()),
734 pathToDisplay(privateResourceDir.absolutePath())));
735 grpWindowsAppData->setVisible(true);
736
737 connect(grpWindowsAppData,
739 [userPath = appDataDir.absolutePath(),
740 privatePath = privateResourceDir.absolutePath()](const QString &link) {
741 if (link == QStringLiteral("copyuser")) {
742 qApp->clipboard()->setText(QDir::toNativeSeparators(userPath));
743 } else if (link == QStringLiteral("copyprivate")) {
744 qApp->clipboard()->setText(QDir::toNativeSeparators(privatePath));
745 } else {
746 qWarning() << "Unexpected link activated in lblWindowsAppDataNote:" << link;
747 }
748 });
749 }
750#endif
751
752
753 const int forcedFontDPI = cfg.readEntry("forcedDpiForQtFontBugWorkaround", -1);
754 chkForcedFontDPI->setChecked(forcedFontDPI > 0);
755 intForcedFontDPI->setValue(forcedFontDPI > 0 ? forcedFontDPI : qt_defaultDpi());
756 intForcedFontDPI->setEnabled(forcedFontDPI > 0);
757 connect(chkForcedFontDPI, SIGNAL(toggled(bool)), intForcedFontDPI, SLOT(setEnabled(bool)));
758
759 m_pasteFormatGroup.addButton(btnDownload, KisClipboard::PASTE_FORMAT_DOWNLOAD);
760 m_pasteFormatGroup.addButton(btnLocal, KisClipboard::PASTE_FORMAT_LOCAL);
761 m_pasteFormatGroup.addButton(btnBitmap, KisClipboard::PASTE_FORMAT_CLIP);
762 m_pasteFormatGroup.addButton(btnAsk, KisClipboard::PASTE_FORMAT_ASK);
763
764 QAbstractButton *button = m_pasteFormatGroup.button(cfg.pasteFormat(false));
765
766 Q_ASSERT(button);
767
768 if (button) {
769 button->setChecked(true);
770 }
771}
772
774{
775 KisConfig cfg(true);
776
777 m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle(true));
778 m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle(true));
779 m_chkSeparateEraserCursor->setChecked(cfg.readEntry<bool>("separateEraserCursor", false));
780 m_cmbEraserCursorShape->setCurrentIndex(cfg.eraserCursorStyle(true));
781 m_cmbEraserOutlineShape->setCurrentIndex(cfg.eraserOutlineStyle(true));
782 setColorSamplerPreviewStyleIndexByValue(m_cmbColorSamplerPreviewStyle, cfg.colorSamplerPreviewStyle(true));
783 m_ssbColorSamplerPreviewThickness->setValue(cfg.colorSamplerPreviewCircleThickness(true));
784 m_nmbColorSamplerPreviewSize->setValue(cfg.colorSamplerPreviewCircleDiameter(true));
785 m_chkColorSamplerPreviewOutlineEnabled->setChecked(cfg.colorSamplerPreviewCircleOutlineEnabled(true));
786
787
788 chkShowRootLayer->setChecked(cfg.showRootLayer(true));
789 m_autosaveCheckBox->setChecked(cfg.autoSaveInterval(true) > 0);
790 //convert to minutes
791 m_autosaveSpinBox->setValue(cfg.autoSaveInterval(true) / 60);
792 chkHideAutosaveFiles->setChecked(true);
793
794 m_undoStackSize->setValue(cfg.undoStackLimit(true));
795 chkCumulativeUndo->setChecked(cfg.useCumulativeUndoRedo(true));
797
798 m_backupFileCheckBox->setChecked(cfg.backupFile(true));
799 cmbBackupFileLocation->setCurrentIndex(0);
800 txtBackupFileSuffix->setText("~");
801 intNumBackupFiles->setValue(1);
802
803 m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting(true));
804 m_changeBrushOutline->setChecked(!cfg.forceAlwaysFullSizedOutline(true));
805 m_showEraserOutlinePainting->setChecked(cfg.showEraserOutlineWhilePainting(true));
806 m_changeEraserBrushOutline->setChecked(!cfg.forceAlwaysFullSizedEraserOutline(true));
807
808#if defined Q_OS_ANDROID || defined Q_OS_MACOS || defined Q_OS_WIN
809 m_chkNativeFileDialog->setChecked(true);
810#else
811 m_chkNativeFileDialog->setChecked(false);
812#endif
813
814 intMaxBrushSize->setValue(1000);
815
816 chkIgnoreHighFunctionKeys->setChecked(cfg.ignoreHighFunctionKeys(true));
817
818
819 chkUseCustomFont->setChecked(false);
820 cmbCustomFont->setCurrentFont(qApp->font());
821 intFontSize->setValue(qApp->font().pointSize());
822
823
824 m_cmbMDIType->setCurrentIndex((int)QMdiArea::TabbedView);
825 m_chkRubberBand->setChecked(cfg.useOpenGL(true));
826 KoColor mdiColor;
827 mdiColor.fromXML(cfg.getMDIBackgroundColor(true));
828 m_mdiColor->setColor(mdiColor);
829 m_backgroundimage->setText(cfg.getMDIBackgroundImage(true));
830 m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true));
831 m_chkCompressKra->setChecked(cfg.compressKra(true));
832 m_chkTrimKra->setChecked(cfg.trimKra(true));
833 m_chkTrimFramesImport->setChecked(cfg.trimFramesImport(true));
834 chkZip64->setChecked(cfg.useZip64(true));
835 m_chkHiDPI->setChecked(true);
836#if defined(Q_OS_WIN) && defined(HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY)
837 m_chkHiDPIFractionalScaling->setChecked(true);
838#endif
839 chkUsageLogging->setChecked(true);
840 m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true));
841 cmbFlowMode->setCurrentIndex(0);
842 chkEnableLongPress->setChecked(cfg.longPressEnabled(true));
843 m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled(true));
844 m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture(true));
845 spnZoomSteps->setValue(cfg.zoomSteps(true));
846 m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity(true));
847 m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars(true));
848 intZoomMarginSize->setValue(cfg.zoomMarginSize(true));
849 m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true));
850 cmbTouchPainting->setCurrentIndex(int(cfg.touchPainting(true)));
851 chkTouchPressureSensitivity->setChecked(true);
852 chkEnableTransformToolAfterPaste->setChecked(cfg.activateTransformToolAfterPaste(true));
853 chkZoomHorizontally->setChecked(cfg.zoomHorizontal(true));
854 m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true));
855
856 KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8());
857 cursorColor.fromQColor(cfg.getCursorMainColor(true));
858 cursorColorButton->setColor(cursorColor);
859
860 KoColor eraserCursorColor(KoColorSpaceRegistry::instance()->rgb8());
861 eraserCursorColor.fromQColor(cfg.getEraserCursorMainColor(true));
862 eraserCursorColorButton->setColor(eraserCursorColor);
863
864
865 m_chkAutoPin->setChecked(cfg.autoPinLayersToTimeline(true));
866 m_chkAdaptivePlaybackRange->setChecked(cfg.adaptivePlaybackRange(false));
867
868 m_urlResourceFolder->setFileName(KoResourcePaths::getAppDataLocation());
869
870 chkForcedFontDPI->setChecked(false);
871 intForcedFontDPI->setValue(qt_defaultDpi());
872 intForcedFontDPI->setEnabled(false);
873
874 chkRenameMergedLayers->setChecked(KisImageConfig(true).renameMergedLayers(true));
875 chkRenamePastedLayers->setChecked(cfg.renamePastedLayers(true));
876 chkRenameDuplicatedLayers->setChecked(KisImageConfig(true).renameDuplicatedLayers(true));
877
878 QAbstractButton *button = m_pasteFormatGroup.button(cfg.pasteFormat(true));
879 Q_ASSERT(button);
880
881 if (button) {
882 button->setChecked(true);
883 }
884}
885
887{
888 KisDlgConfigureCumulativeUndo dlg(m_cumulativeUndoData, m_undoStackSize->value(), this);
889 if (dlg.exec() == KoDialog::Accepted) {
891 }
892}
893
895{
896 bool circleSettingsVisible = index == int(KisConfig::ColorSamplerPreviewStyle::Circle);
897 m_frmColorSamplerCircleSettings->setVisible(circleSettingsVisible);
898}
899
901{
902 m_lblColorSamplerPreviewSizePreview->setDiameter(value);
903}
904
906{
907 m_lblColorSamplerPreviewSizePreview->setThickness(value/100.0);
908}
909
911{
912 m_lblColorSamplerPreviewSizePreview->setOutlineEnabled(value);
913}
914
915void GeneralTab::setButtonGroupEnabled(const QButtonGroup &buttonGroup, bool value)
916{
917 Q_FOREACH(QAbstractButton* button, buttonGroup.buttons()) {
918 if (button) {
919 button->setEnabled(value);
920 }
921 }
922}
923
925{
926 return (CursorStyle)m_cmbCursorShape->currentIndex();
927}
928
930{
931 return (OutlineStyle)m_cmbOutlineShape->currentIndex();
932}
933
935{
936 return (CursorStyle)m_cmbEraserCursorShape->currentIndex();
937}
938
940{
941 return (OutlineStyle)m_cmbEraserOutlineShape->currentIndex();
942}
943
948
950{
951 return m_nmbColorSamplerPreviewSize->value();
952}
953
955{
956 return m_ssbColorSamplerPreviewThickness->value();
957}
958
960{
961 return m_chkColorSamplerPreviewOutlineEnabled->isChecked();
962}
963
965{
966 return m_chkColorSamplerPreviewExtraCircles->isChecked();
967}
968
969
971{
972 return (KisConfig::SessionOnStartup)cmbStartupSession->currentIndex();
973}
974
976{
977 return chkSaveSessionOnQuit->isChecked();
978}
979
981{
982 return chkShowRootLayer->isChecked();
983}
984
986{
987 //convert to seconds
988 return m_autosaveCheckBox->isChecked() ? m_autosaveSpinBox->value() * 60 : 0;
989}
990
992{
993 return m_undoStackSize->value();
994}
995
997{
998 return m_showOutlinePainting->isChecked();
999}
1000
1002{
1003 return m_showEraserOutlinePainting->isChecked();
1004}
1005
1007{
1008 return m_cmbMDIType->currentIndex();
1009}
1010
1012{
1013 return m_chkCanvasMessages->isChecked();
1014}
1015
1017{
1018 return m_chkCompressKra->isChecked();
1019}
1020
1022{
1023 return m_chkTrimKra->isChecked();
1024}
1025
1027{
1028 return m_chkTrimFramesImport->isChecked();
1029}
1030
1032{
1033 return cmbDefaultExportFileType->currentData().toString();
1034}
1035
1037{
1038 return chkZip64->isChecked();
1039}
1040
1042{
1043 return m_radioToolOptionsInDocker->isChecked();
1044}
1045
1047{
1048 return spnZoomSteps->value();
1049}
1050
1052{
1053 return chkEnableLongPress->isChecked();
1054}
1055
1057{
1058 return m_groupBoxKineticScrollingSettings->isChecked();
1059}
1060
1062{
1063 return m_cmbKineticScrollingGesture->currentIndex();
1064}
1065
1067{
1068 return m_kineticScrollingSensitivitySlider->value();
1069}
1070
1072{
1073 return m_chkKineticScrollingHideScrollbars->isChecked();
1074}
1075
1077{
1078 return intZoomMarginSize->value();
1079}
1080
1082{
1083 return m_chkSwitchSelectionCtrlAlt->isChecked();
1084}
1085
1087{
1088 return m_chkConvertOnImport->isChecked();
1089}
1090
1092{
1093 return m_chkAutoPin->isChecked();
1094}
1095
1097{
1098 return m_chkAdaptivePlaybackRange->isChecked();
1099}
1100
1102{
1103 return m_chkAutoZoom->isChecked();
1104}
1105
1107{
1108 return chkForcedFontDPI->isChecked() ? intForcedFontDPI->value() : -1;
1109}
1110
1112{
1113 // Order is synchronized with KisConfig::ColorSamplerPreviewStyle.
1114 cmb->addItems({
1115 i18nc("Preview option for no color sampler", "None"),
1116 i18nc("Preview option for a circular/ring-shaped color sampler", "Circle"),
1117 i18nc("Preview option for a rectangular color sampler left of the cursor", "Rectangle Left"),
1118 i18nc("Preview option for a rectangular color sampler right of the cursor", "Rectangle Right"),
1119 i18nc("Preview option for a rectangular color sampler above the cursor", "Rectangle Above"),
1120 });
1121}
1122
1124{
1125 cmb->setCurrentIndex(int(style));
1126}
1127
1132
1134{
1135 return chkRenameMergedLayers->isChecked();
1136}
1137
1139{
1140 return chkRenamePastedLayers->isChecked();
1141}
1142
1144{
1145 return chkRenameDuplicatedLayers->isChecked();
1146}
1147
1149{
1150 KoFileDialog dialog(this, KoFileDialog::OpenFile, "BackgroundImages");
1151 dialog.setCaption(i18n("Select a Background Image"));
1152 dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
1153 dialog.setImageFilters();
1154
1155 QString fn = dialog.filename();
1156 // dialog box was canceled or somehow no file was selected
1157 if (fn.isEmpty()) {
1158 return;
1159 }
1160
1161 QImage image(fn);
1162 if (image.isNull()) {
1163 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("%1 is not a valid image file!", fn));
1164 }
1165 else {
1166 m_backgroundimage->setText(fn);
1167 }
1168}
1169
1171{
1172 // clearing the background image text will implicitly make the background color be used
1173 m_backgroundimage->setText("");
1174}
1175
1177{
1178 const QFileInfo fi(m_urlResourceFolder->fileName());
1179 if (!fi.isWritable()) {
1180 grpNonWritableLocation->setPixmap(
1181 grpNonWritableLocation->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
1182 grpNonWritableLocation->setText(
1183 i18nc("@info resource folder", "<b>Warning:</b> this location is not writable."));
1184 grpNonWritableLocation->setVisible(true);
1185 } else {
1186 grpNonWritableLocation->setVisible(false);
1187 }
1188}
1189
1191{
1192 group_subWinMode->setEnabled(mdi_mode == QMdiArea::SubWindowView);
1193}
1194
1196{
1197 chkTouchPressureSensitivity->setEnabled(touchPainting != int(KisConfig::TOUCH_PAINTING_DISABLED));
1198}
1199
1200
1201#include "kactioncollection.h"
1202#include "KisActionsSnapshot.h"
1203
1204ShortcutSettingsTab::ShortcutSettingsTab(QWidget *parent, const char *name)
1205 : QWidget(parent)
1206{
1207 setObjectName(name);
1208
1209 QGridLayout * l = new QGridLayout(this);
1210 l->setContentsMargins(0, 0, 0, 0);
1211 m_page = new WdgShortcutSettings(this);
1212 l->addWidget(m_page, 0, 0);
1213
1214
1215 m_snapshot.reset(new KisActionsSnapshot);
1216
1217 KisKActionCollection *collection =
1219
1220 Q_FOREACH (QAction *action, collection->actions()) {
1221 m_snapshot->addAction(action->objectName(), action);
1222 }
1223
1224 QMap<QString, KisKActionCollection*> sortedCollections =
1225 m_snapshot->actionCollections();
1226
1227 for (auto it = sortedCollections.constBegin(); it != sortedCollections.constEnd(); ++it) {
1228 m_page->addCollection(it.value(), it.key());
1229 }
1230}
1231
1235
1240
1246
1251
1252ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name)
1253 : QWidget(parent)
1254 , m_proofModel(new KisProofingConfigModel())
1255{
1256 setObjectName(name);
1257
1258 // XXX: Make sure only profiles that fit the specified color model
1259 // are shown in the profile combos
1260
1261 QGridLayout * l = new QGridLayout(this);
1262 l->setContentsMargins(0, 0, 0, 0);
1263 m_page = new WdgColorSettings(this);
1264 l->addWidget(m_page, 0, 0);
1265
1266 KisConfig cfg(true);
1267
1269
1270 if (!m_colorManagedByOS) {
1271 m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile());
1272 connect(m_page->chkUseSystemMonitorProfile, SIGNAL(toggled(bool)), this, SLOT(toggleAllowMonitorProfileSelection(bool)));
1273 }
1274 m_page->chkUseSystemMonitorProfile->setVisible(!m_colorManagedByOS);
1275
1276 m_page->useDefColorSpace->setChecked(cfg.useDefaultColorSpace());
1277 connect(m_page->useDefColorSpace, SIGNAL(toggled(bool)), this, SLOT(toggleUseDefaultColorSpace(bool)));
1279 for (QList<KoID>::iterator id = colorSpaces.begin(); id != colorSpaces.end(); /* nop */) {
1281 id = colorSpaces.erase(id);
1282 } else {
1283 ++id;
1284 }
1285 }
1286 m_page->cmbWorkingColorSpace->setIDList(colorSpaces);
1287 m_page->cmbWorkingColorSpace->setCurrent(cfg.workingColorSpace());
1288 m_page->cmbWorkingColorSpace->setEnabled(cfg.useDefaultColorSpace());
1289
1290 if (!m_colorManagedByOS) {
1291 m_page->bnAddColorProfile->setIcon(koIcon("document-import-16"));
1292 connect(m_page->bnAddColorProfile, SIGNAL(clicked()), SLOT(installProfile()));
1293 }
1294 m_page->bnAddColorProfile->setVisible(!m_colorManagedByOS);
1295
1296 {
1297 QStringList profiles;
1298 QMap<QString, const KoColorProfile *> profileList;
1299 Q_FOREACH(const KoColorProfile *profile, KoColorSpaceRegistry::instance()->profilesFor(RGBAColorModelID.id())) {
1300 profileList[profile->name()] = profile;
1301 profiles.append(profile->name());
1302 }
1303
1304 std::sort(profiles.begin(), profiles.end());
1305 Q_FOREACH (const QString profile, profiles) {
1306 m_page->cmbColorProfileForEXR->addSqueezedItem(profile);
1307 }
1308
1310 const QString defaultProfile = KoColorSpaceRegistry::instance()->defaultProfileForColorSpace(colorSpaceId);
1311 const QString userProfile = cfg.readEntry("ExrDefaultColorProfile", defaultProfile);
1312
1313 m_page->cmbColorProfileForEXR->setCurrent(profiles.contains(userProfile) ? userProfile : defaultProfile);
1314 }
1315
1316
1317 if (!m_colorManagedByOS) {
1318 QFormLayout *monitorProfileGrid = new QFormLayout(m_page->monitorprofileholder);
1319 monitorProfileGrid->setContentsMargins(0, 0, 0, 0);
1320 for(int i = 0; i < QGuiApplication::screens().count(); ++i) {
1321 QLabel *lbl = new QLabel(i18nc("The number of the screen (ordinal) and shortened 'name' of the screen (model + resolution)", "Screen %1 (%2):", i + 1, shortNameOfDisplay(i)));
1322 lbl->setWordWrap(true);
1325 cmb->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
1326 monitorProfileGrid->addRow(lbl, cmb);
1328 }
1329
1330 // disable if not Linux as KisColorManager is not yet implemented outside Linux
1331#ifndef Q_OS_LINUX
1332 m_page->chkUseSystemMonitorProfile->setChecked(false);
1333 m_page->chkUseSystemMonitorProfile->setDisabled(true);
1334 m_page->chkUseSystemMonitorProfile->setHidden(true);
1335#endif
1336
1337 refillMonitorProfiles(KoID("RGBA"));
1338
1339 for(int i = 0; i < QApplication::screens().count(); ++i) {
1340 if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) {
1341 m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i));
1342 }
1343 }
1344 } else {
1345 QVBoxLayout *vboxLayout = new QVBoxLayout(m_page->monitorprofileholder);
1346 vboxLayout->setContentsMargins(0, 0, 0, 0);
1347 vboxLayout->addItem(new QSpacerItem(20,20));
1348
1349 QGroupBox *groupBox = new QGroupBox(i18n("Display's color space is managed by the operating system"));
1350 vboxLayout->addWidget(groupBox);
1351
1352 QFormLayout *monitorProfileGrid = new QFormLayout(groupBox);
1353 monitorProfileGrid->setContentsMargins(0, 0, 0, 0);
1354
1356 new QCheckBox(i18n("Enable canvas color management"), this);
1357
1359 i18n("<p>Enabling canvas color management automatically creates "
1360 "a separate native surface for the canvas. It might cause "
1361 "performance issues on some systems.</p>"
1362 ""
1363 "<p>If color management is disabled, Krita will render "
1364 "the canvas into the surface of the main window, which "
1365 "is considered sRGB. It will cause two limitations:"
1366 ""
1367 "<ol>"
1368 " <li>the color gamut will be limited to sRGB</li>"
1369 " <li>color proofing mode will be limited to \"use global display settings\", "
1370 " i.e. paper white proofing will become impossible</li>"
1371 "</ol>"
1372 "</p>"));
1373
1374 monitorProfileGrid->addRow(m_chkEnableCanvasColorSpaceManagement);
1375
1376 // surface color space
1378 m_canvasSurfaceColorSpace->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
1379 QLabel *canvasSurfaceColorSpaceLbl = new QLabel(i18n("Canvas surface color space:"), this);
1380 monitorProfileGrid->addRow(canvasSurfaceColorSpaceLbl, m_canvasSurfaceColorSpace);
1381
1382 m_canvasSurfaceColorSpace->addSqueezedItem(i18n("Preferred by operating system"), QVariant::fromValue(CanvasSurfaceMode::Preferred));
1383 m_canvasSurfaceColorSpace->addSqueezedItem(i18n("Rec 709 Gamma 2.2"), QVariant::fromValue(CanvasSurfaceMode::Rec709g22));
1384 m_canvasSurfaceColorSpace->addSqueezedItem(i18n("Rec 709 Linear"), QVariant::fromValue(CanvasSurfaceMode::Rec709g10));
1385 m_canvasSurfaceColorSpace->addSqueezedItem(i18n("Rec 2020 PQ"), QVariant::fromValue(CanvasSurfaceMode::Rec2020pq));
1386 m_canvasSurfaceColorSpace->addSqueezedItem(i18n("Unmanaged (testing only)"), QVariant::fromValue(CanvasSurfaceMode::Unmanaged));
1387
1388 m_canvasSurfaceColorSpace->setToolTip(
1389 i18n("<p>Color space of the pixels that are transferred to the "
1390 "window compositor. Use \"preferred\" space unless you know "
1391 "what you are doing</p>"));
1392
1393 // surface bit depth
1395 m_canvasSurfaceBitDepth->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
1396 QLabel *canvasSurfaceBitDepthLbl = new QLabel(i18n("Canvas surface bit depth (needs restart):"), this);
1397 monitorProfileGrid->addRow(canvasSurfaceBitDepthLbl, m_canvasSurfaceBitDepth);
1398
1399 m_canvasSurfaceBitDepth->addSqueezedItem(i18n("Auto"), QVariant::fromValue(CanvasSurfaceBitDepthMode::DepthAuto));
1400 m_canvasSurfaceBitDepth->addSqueezedItem(i18n("8-bit"), QVariant::fromValue(CanvasSurfaceBitDepthMode::Depth8Bit));
1401 m_canvasSurfaceBitDepth->addSqueezedItem(i18n("10-bit"), QVariant::fromValue(CanvasSurfaceBitDepthMode::Depth10Bit));
1402
1403 m_canvasSurfaceBitDepth->setToolTip(
1404 i18n("<p>The bit depth of the color that is passed to the window "
1405 "compositor. You should switch into 10-bit mode if you want to use "
1406 "HDR capabilities of your display</p>"));
1407
1408 const QString currentBitBepthString = QSurfaceFormat::defaultFormat().redBufferSize() == 10 ? i18n("10-bit") : i18n("8-bit");
1409 QLabel *currentCanvasSurfaceBitDepthLbl = new QLabel(i18n("Current canvas surface bit depth:"), this);
1410 QLabel *currentCanvasSurfaceBitDepth = new QLabel(currentBitBepthString, this);
1411 monitorProfileGrid->addRow(currentCanvasSurfaceBitDepthLbl, currentCanvasSurfaceBitDepth);
1412
1413 vboxLayout->addItem(new QSpacerItem(20,20));
1414
1416 QTextBrowser *preferredLbl = new QTextBrowser(this);
1417 preferredLbl->setText(i18n("Color space preferred by the operating system:\n%1", KisPlatformPluginInterfaceFactory::instance()->osPreferredColorSpaceReport(mainWindow)));
1418 preferredLbl->setReadOnly(true);
1419
1420 QHBoxLayout *colorDescriptionChoice = new QHBoxLayout();
1421 vboxLayout->addLayout(colorDescriptionChoice);
1422
1423 QLabel *descriptionChoiceLabel = new QLabel(i18n("Diagram:"));
1424 colorDescriptionChoice->addWidget(descriptionChoiceLabel);
1425
1426 QRadioButton *containerSpace = new QRadioButton(i18nc("@info:radiobutton", "Preferred Space"), this);
1427 colorDescriptionChoice->addWidget(containerSpace);
1428 containerSpace->setToolTip(i18nc("@info:tooltip", "This is the space preferred by the operating system."));
1429 m_preferredSpaceGraphicMode.addButton(containerSpace, PreferredSpace);
1430
1431 QRadioButton *masteringSpace = new QRadioButton(i18nc("@info:radiobutton", "Current Display"), this);
1432 colorDescriptionChoice->addWidget(masteringSpace);
1433 m_preferredSpaceGraphicMode.addButton(masteringSpace, MasteringSpace);
1434 masteringSpace->setToolTip(i18nc("@info:tooltip", "This is the space representing the currently active display."));
1435
1436 QHBoxLayout *colorDescriptionLayout = new QHBoxLayout();
1437 vboxLayout->addLayout(colorDescriptionLayout);
1439 colorDescriptionLayout->addWidget(m_preferredSpaceGraphic);
1440 colorDescriptionLayout->addWidget(preferredLbl);
1441
1442 containerSpace->setChecked(true);
1443 colorDescriptionChoice->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
1444
1445 m_preferredSpaceGraphic->setFixedSize(QSize(200, 200));
1447 connect(&m_preferredSpaceGraphicMode, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(updatePreferredSpaceGraphic()));
1451
1453
1454 {
1455 auto mode = cfg.canvasSurfaceColorSpaceManagementMode();
1456 int index = m_canvasSurfaceColorSpace->findData(QVariant::fromValue(mode));
1457 KIS_SAFE_ASSERT_RECOVER(index >= 0) {
1458 index = 0;
1459 }
1460 m_canvasSurfaceColorSpace->setCurrentIndex(index);
1461 }
1462
1463 {
1464 auto mode = cfg.canvasSurfaceBitDepthMode();
1465 int index = m_canvasSurfaceBitDepth->findData(QVariant::fromValue(mode));
1466 KIS_SAFE_ASSERT_RECOVER(index >= 0) {
1467 index = 0;
1468 }
1469 m_canvasSurfaceBitDepth->setCurrentIndex(index);
1470 }
1471
1472 connect(m_chkEnableCanvasColorSpaceManagement, &QCheckBox::toggled, m_canvasSurfaceColorSpace, &QWidget::setEnabled);
1474
1475 connect(m_chkEnableCanvasColorSpaceManagement, &QCheckBox::toggled, canvasSurfaceColorSpaceLbl, &QWidget::setEnabled);
1476 canvasSurfaceColorSpaceLbl->setEnabled(m_chkEnableCanvasColorSpaceManagement->isChecked());
1477
1478 connect(m_chkEnableCanvasColorSpaceManagement, &QCheckBox::toggled, m_canvasSurfaceBitDepth, &QWidget::setEnabled);
1480
1481 connect(m_chkEnableCanvasColorSpaceManagement, &QCheckBox::toggled, canvasSurfaceBitDepthLbl, &QWidget::setEnabled);
1482 canvasSurfaceBitDepthLbl->setEnabled(m_chkEnableCanvasColorSpaceManagement->isChecked());
1483 }
1484
1485 m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation());
1486 m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization());
1487 m_page->chkForcePaletteColor->setChecked(cfg.forcePaletteColors());
1488 m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent());
1489 KisImageConfig cfgImage(true);
1490
1494 KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration();
1495
1496 m_page->wdgProofingOptions->setProofingConfig(proofingConfig);
1497
1498 m_proofModel->data.set(*proofingConfig.data());
1499
1500 connect(m_page->chkBlackpoint, SIGNAL(toggled(bool)), this, SLOT(updateProofingDisplayInfo()));
1501 connect(m_page->cmbMonitorIntent, SIGNAL(currentIndexChanged(int)), this, SLOT(updateProofingDisplayInfo()));
1503
1506 m_pasteBehaviourGroup.addButton(m_page->radioPasteAsk, KisClipboard::PASTE_ASK);
1507
1508 QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour());
1509 Q_ASSERT(button);
1510
1511 if (button) {
1512 button->setChecked(true);
1513 }
1514
1515 if (!m_colorManagedByOS) {
1517 }
1518}
1519
1521{
1523
1524 KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC");
1525 dialog.setCaption(i18n("Install Color Profiles"));
1526 dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
1527 dialog.setMimeTypeFilters(QStringList() << "application/vnd.iccprofile", "application/vnd.iccprofile");
1528 QStringList profileNames = dialog.filenames();
1529
1531 Q_ASSERT(iccEngine);
1532
1533 QString saveLocation = KoResourcePaths::saveLocation("icc_profiles");
1534
1535 Q_FOREACH (const QString &profileName, profileNames) {
1536 if (!QFile::copy(profileName, saveLocation + QFileInfo(profileName).fileName())) {
1537 qWarning() << "Could not install profile!" << saveLocation + QFileInfo(profileName).fileName();
1538 continue;
1539 }
1540 iccEngine->addProfile(saveLocation + QFileInfo(profileName).fileName());
1541 }
1542
1543 KisConfig cfg(true);
1544 refillMonitorProfiles(KoID("RGBA"));
1545
1546 for(int i = 0; i < QApplication::screens().count(); ++i) {
1547 if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) {
1548 m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i));
1549 }
1550 }
1551
1552}
1553
1555{
1557
1558 KisConfig cfg(true);
1559
1560 if (useSystemProfile) {
1562 if (devices.size() == QApplication::screens().count()) {
1563 for(int i = 0; i < QApplication::screens().count(); ++i) {
1564 m_monitorProfileWidgets[i]->clear();
1565 QString monitorForScreen = cfg.monitorForScreen(i, devices[i]);
1566 Q_FOREACH (const QString &device, devices) {
1567 m_monitorProfileLabels[i]->setText(i18nc("The number of the screen (ordinal) and shortened 'name' of the screen (model + resolution)", "Screen %1 (%2):", i + 1, shortNameOfDisplay(i)));
1568 m_monitorProfileWidgets[i]->addSqueezedItem(KisColorManager::instance()->deviceName(device), device);
1569 if (devices[i] == monitorForScreen) {
1570 m_monitorProfileWidgets[i]->setCurrentIndex(i);
1571 }
1572 }
1573 }
1574 }
1575 }
1576 else {
1577 refillMonitorProfiles(KoID("RGBA"));
1578
1579 for(int i = 0; i < QApplication::screens().count(); ++i) {
1580 if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) {
1581 m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i));
1582 }
1583 }
1584 }
1585}
1586
1588{
1589 m_page->cmbWorkingColorSpace->setEnabled(useDefColorSpace);
1590}
1591
1593{
1594 m_page->cmbWorkingColorSpace->setCurrent("RGBA");
1595
1597 const QString defaultProfile = KoColorSpaceRegistry::instance()->defaultProfileForColorSpace(colorSpaceId);
1598 m_page->cmbColorProfileForEXR->setCurrent(defaultProfile);
1599
1600 KisConfig cfg(true);
1601
1602 if (!m_colorManagedByOS) {
1603 refillMonitorProfiles(KoID("RGBA"));
1604 } else {
1606
1607 {
1608 auto mode = cfg.canvasSurfaceColorSpaceManagementMode(true);
1609 int index = m_canvasSurfaceColorSpace->findData(QVariant::fromValue(mode));
1610 KIS_SAFE_ASSERT_RECOVER(index >= 0) {
1611 index = 0;
1612 }
1613 m_canvasSurfaceColorSpace->setCurrentIndex(index);
1614 }
1615
1616 {
1617 auto mode = cfg.canvasSurfaceBitDepthMode(true);
1618 int index = m_canvasSurfaceBitDepth->findData(QVariant::fromValue(mode));
1619 KIS_SAFE_ASSERT_RECOVER(index >= 0) {
1620 index = 0;
1621 }
1622 m_canvasSurfaceBitDepth->setCurrentIndex(index);
1623 }
1624 }
1625
1626 KisImageConfig cfgImage(true);
1627 KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(true);
1628 m_page->wdgProofingOptions->setProofingConfig(proofingConfig);
1629
1630 m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation(true));
1631 m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization(true));
1632 m_page->chkForcePaletteColor->setChecked(cfg.forcePaletteColors(true));
1633 m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent(true));
1634 if (!m_colorManagedByOS) {
1635 m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile(true));
1636 }
1637 QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour(true));
1638 Q_ASSERT(button);
1639 if (button) {
1640 button->setChecked(true);
1641 }
1642}
1643
1644
1646{
1648
1649 for (int i = 0; i < QApplication::screens().count(); ++i) {
1650 m_monitorProfileWidgets[i]->clear();
1651 }
1652
1653 QMap<QString, const KoColorProfile *> profileList;
1654 Q_FOREACH(const KoColorProfile *profile, KoColorSpaceRegistry::instance()->profilesFor(colorSpaceId.id())) {
1655 profileList[profile->name()] = profile;
1656 }
1657
1658 Q_FOREACH (const KoColorProfile *profile, profileList.values()) {
1659 //qDebug() << "Profile" << profile->name() << profile->isSuitableForDisplay() << csf->defaultProfile();
1660 if (profile->isSuitableForDisplay()) {
1661 for (int i = 0; i < QApplication::screens().count(); ++i) {
1662 m_monitorProfileWidgets[i]->addSqueezedItem(profile->name());
1663 }
1664 }
1665 }
1666
1667 for (int i = 0; i < QApplication::screens().count(); ++i) {
1668 m_monitorProfileLabels[i]->setText(i18nc("The number of the screen (ordinal) and shortened 'name' of the screen (model + resolution)", "Screen %1 (%2):", i + 1, shortNameOfDisplay(i)));
1670 }
1671}
1672
1675 options.first = KoColorConversionTransformation::Intent(m_page->cmbMonitorIntent->currentIndex());
1677 options.second.setFlag(KoColorConversionTransformation::BlackpointCompensation, m_page->chkBlackpoint->isChecked());
1678 m_page->wdgProofingOptions->setDisplayConfigOptions(options);
1679}
1680
1682{
1683 if (!m_preferredSpaceGraphic) return;
1684 if (!KisPlatformPluginInterfaceFactory::instance()->surfaceColorManagedByOS()) return;
1687 KoColorimetryUtils::xyY whitePoint;
1688
1689#ifdef Q_OS_LINUX
1690#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1691 KisRootSurfaceInfoProxy proxy(mainWindow);
1692 std::optional<KisSurfaceColorimetry::SurfaceDescription> currentDescription = proxy.currentSurfaceDescription();
1693 if (m_preferredSpaceGraphicMode.checkedId() == PreferredSpace) {
1694 if (currentDescription) {
1695 if (std::holds_alternative<KisSurfaceColorimetry::Colorimetry>(currentDescription->colorSpace.primaries)) {
1696 auto col = std::get<KisSurfaceColorimetry::Colorimetry>(currentDescription->colorSpace.primaries);
1697 colorants << col.red().toxyY() << col.green().toxyY() << col.blue().toxyY();
1698 whitePoint = col.white().toxyY();
1699 m_preferredSpaceGraphic->setRGBData(whitePoint, colorants);
1700 } else {
1701 bool enable = true;
1702 auto named = std::get<KisSurfaceColorimetry::NamedPrimaries>(currentDescription->colorSpace.primaries);
1714 } else {
1715 enable = false;
1716 }
1717
1718 if (enable) {
1719 colorants << col.red().toxyY() << col.green().toxyY() << col.blue().toxyY();
1720 whitePoint = col.white().toxyY();
1721 m_preferredSpaceGraphic->setRGBData(whitePoint, colorants);
1722 } else {
1723 m_preferredSpaceGraphic->setProfileDataAvailable(false);
1724 }
1725
1726 }
1727 } else {
1728 m_preferredSpaceGraphic->setProfileDataAvailable(false);
1729 }
1730 } else if(m_preferredSpaceGraphicMode.checkedId() == MasteringSpace) {
1731 if (currentDescription && currentDescription->masteringInfo) {
1732 auto col = currentDescription->masteringInfo->primaries;
1733 colorants << col.red().toxyY() << col.green().toxyY() << col.blue().toxyY();
1734 whitePoint = col.white().toxyY();
1735
1736 m_preferredSpaceGraphic->setRGBData(whitePoint, colorants);
1737 } else {
1738 m_preferredSpaceGraphic->setProfileDataAvailable(false);
1739 }
1740 }
1741#endif
1742#endif
1743 m_preferredSpaceGraphic->update();
1744}
1745
1746//---------------------------------------------------------------------------------------------------
1747
1749{
1750 KisConfig cfg(true);
1751 const KisCubicCurve curve(cfg.pressureTabletCurve(true));
1752 m_page->pressureCurve->setCurve(curve);
1753
1754 m_page->chkUseRightMiddleClickWorkaround->setChecked(
1755 KisConfig(true).useRightMiddleTabletButtonWorkaround(true));
1756
1757#if defined Q_OS_WIN && (defined QT5_HAS_WINTAB_SWITCH || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
1758 m_page->radioWintab->setChecked(!cfg.useWin8PointerInput(true));
1759 m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput(true));
1760#else
1761 m_page->grpTabletApi->setVisible(false);
1762#endif
1763
1764#if KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_PAGE_UP_DOWN
1765 m_page->chkUsePageUpDownMouseButtonEmulationWorkaround->setChecked(
1766 cfg.usePageUpDownMouseButtonEmulationWorkaround(true));
1767#endif
1768
1769#if KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_HIGH_FUNCTION_KEYS
1770 m_page->chkUseHighFunctionKeyMouseButtonEmulationWorkaround->setChecked(
1771 cfg.useHighFunctionKeyMouseButtonEmulationWorkaround(true));
1772#endif
1773
1774#if KRITA_QT_HAS_ANDROID_IGNORE_HISTORIC_TABLET_EVENTS
1775 m_page->chkUseIgnoreHistoricTabletEventsWorkaround->setChecked(cfg.useIgnoreHistoricTabletEventsWorkaround(true));
1776#endif
1777
1778 m_page->chkUseTimestampsForBrushSpeed->setChecked(false);
1779 m_page->intMaxAllowedBrushSpeed->setValue(30);
1780 m_page->intBrushSpeedSmoothing->setValue(3);
1781 m_page->tiltDirectionOffsetAngle->setAngle(0);
1782}
1783
1784TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget(parent)
1785{
1786 setObjectName(name);
1787
1788 QGridLayout * l = new QGridLayout(this);
1789 l->setContentsMargins(0, 0, 0, 0);
1790 m_page = new WdgTabletSettings(this);
1791 l->addWidget(m_page, 0, 0);
1792
1793 KisConfig cfg(true);
1794 const KisCubicCurve curve(cfg.pressureTabletCurve());
1795 m_page->pressureCurve->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
1796 m_page->pressureCurve->setCurve(curve);
1797
1798 m_page->chkUseRightMiddleClickWorkaround->setChecked(
1800
1801#if defined Q_OS_WIN && (defined QT5_HAS_WINTAB_SWITCH || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
1802# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1803 QString actualTabletProtocol = "<unknown>";
1804 using QWindowsApplication = QNativeInterface::Private::QWindowsApplication;
1805 if (auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration())) {
1806 actualTabletProtocol = nativeWindowsApp->isWinTabEnabled() ? "WinTab" : "Windows Ink";
1807 }
1808 m_page->grpTabletApi->setTitle(i18n("Tablet Input API (currently active API: \"%1\")", actualTabletProtocol));
1809# endif
1810 m_page->radioWintab->setChecked(!cfg.useWin8PointerInput());
1811 m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput());
1812
1813 connect(m_page->btnResolutionSettings, SIGNAL(clicked()), SLOT(slotResolutionSettings()));
1814 connect(m_page->radioWintab, SIGNAL(toggled(bool)), m_page->btnResolutionSettings, SLOT(setEnabled(bool)));
1815 m_page->btnResolutionSettings->setEnabled(m_page->radioWintab->isChecked());
1816#else
1817 m_page->grpTabletApi->setVisible(false);
1818#endif
1819 connect(m_page->btnTabletTest, SIGNAL(clicked()), SLOT(slotTabletTest()));
1820
1821#ifdef Q_OS_WIN
1822 m_page->chkUseTimestampsForBrushSpeed->setText(i18n("Use tablet driver timestamps for brush speed (may cause severe artifacts when using WinTab tablet API)"));
1823#else
1824 m_page->chkUseTimestampsForBrushSpeed->setText(i18n("Use tablet driver timestamps for brush speed"));
1825#endif
1826 m_page->chkUseTimestampsForBrushSpeed->setChecked(cfg.readEntry("useTimestampsForBrushSpeed", false));
1827
1828#if KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_PAGE_UP_DOWN
1829 m_page->chkUsePageUpDownMouseButtonEmulationWorkaround->setChecked(
1830 cfg.usePageUpDownMouseButtonEmulationWorkaround());
1831#else
1832 m_page->chkUsePageUpDownMouseButtonEmulationWorkaround->hide();
1833#endif
1834
1835#if KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_HIGH_FUNCTION_KEYS
1836 m_page->chkUseHighFunctionKeyMouseButtonEmulationWorkaround->setChecked(
1837 cfg.useHighFunctionKeyMouseButtonEmulationWorkaround());
1838#else
1839 m_page->chkUseHighFunctionKeyMouseButtonEmulationWorkaround->hide();
1840#endif
1841
1842#if KRITA_QT_HAS_ANDROID_IGNORE_HISTORIC_TABLET_EVENTS
1843 m_page->chkUseIgnoreHistoricTabletEventsWorkaround->setChecked(cfg.useIgnoreHistoricTabletEventsWorkaround());
1844#else
1845 m_page->chkUseIgnoreHistoricTabletEventsWorkaround->hide();
1846#endif
1847
1848 m_page->intMaxAllowedBrushSpeed->setRange(1, 100);
1849 m_page->intMaxAllowedBrushSpeed->setValue(cfg.readEntry("maxAllowedSpeedValue", 30));
1850 KisSpinBoxI18nHelper::install(m_page->intMaxAllowedBrushSpeed, [](int value) {
1851 // i18n: This is meant to be used in a spinbox so keep the {n} in the text
1852 // and it will be substituted by the number. The text before will be
1853 // used as the prefix and the text after as the suffix
1854 return i18np("Maximum brush speed: {n} px/ms", "Maximum brush speed: {n} px/ms", value);
1855 });
1856
1857 m_page->intBrushSpeedSmoothing->setRange(3, 100);
1858 m_page->intBrushSpeedSmoothing->setValue(cfg.readEntry("speedValueSmoothing", 3));
1859 KisSpinBoxI18nHelper::install(m_page->intBrushSpeedSmoothing, [](int value) {
1860 // i18n: This is meant to be used in a spinbox so keep the {n} in the text
1861 // and it will be substituted by the number. The text before will be
1862 // used as the prefix and the text after as the suffix
1863 return i18np("Brush speed smoothing: {n} sample", "Brush speed smoothing: {n} samples", value);
1864 });
1865
1866 m_page->tiltDirectionOffsetAngle->setDecimals(0);
1867 m_page->tiltDirectionOffsetAngle->setRange(-180, 180);
1868 // the angle is saved in clockwise direction to be consistent with Drawing Angle, so negate
1869 m_page->tiltDirectionOffsetAngle->setAngle(-cfg.readEntry("tiltDirectionOffset", 0.0));
1870 m_page->tiltDirectionOffsetAngle->setPrefix(i18n("Pen tilt direction offset: "));
1871 m_page->tiltDirectionOffsetAngle->setFlipOptionsMode(KisAngleSelector::FlipOptionsMode_MenuButton);
1872}
1873
1875{
1876 TabletTestDialog tabletTestDialog(this);
1877 tabletTestDialog.exec();
1878}
1879
1880#ifdef Q_OS_WIN
1882#endif
1883
1885{
1886#ifdef Q_OS_WIN
1888 dlg.exec();
1889#endif
1890}
1891
1892
1893//---------------------------------------------------------------------------------------------------
1895
1897{
1898 return KisImageConfig(true).totalRAM();
1899}
1900
1902{
1903 return intMemoryLimit->value() - intPoolLimit->value();
1904}
1905
1906PerformanceTab::PerformanceTab(QWidget *parent, const char *name)
1907 : WdgPerformanceSettings(parent, name)
1908 , m_frameRateModel(new KisFrameRateLimitModel())
1909{
1910 KisImageConfig cfg(true);
1911 const double totalRAM = cfg.totalRAM();
1912 lblTotalMemory->setText(KFormat().formatByteSize(totalRAM * 1024 * 1024, 0, KFormat::IECBinaryDialect, KFormat::UnitMegaByte));
1913
1914 KisSpinBoxI18nHelper::setText(sliderMemoryLimit, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
1915 sliderMemoryLimit->setRange(1, 100, 2);
1916 sliderMemoryLimit->setSingleStep(0.01);
1917
1918 KisSpinBoxI18nHelper::setText(sliderPoolLimit, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
1919 sliderPoolLimit->setRange(0, 20, 2);
1920 sliderPoolLimit->setSingleStep(0.01);
1921
1922 KisSpinBoxI18nHelper::setText(sliderUndoLimit, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
1923 sliderUndoLimit->setRange(0, 50, 2);
1924 sliderUndoLimit->setSingleStep(0.01);
1925
1926 intMemoryLimit->setMinimumWidth(80);
1927 intPoolLimit->setMinimumWidth(80);
1928 intUndoLimit->setMinimumWidth(80);
1929
1930 {
1931 formLayout->takeRow(2);
1932 label_5->setVisible(false);
1933 intPoolLimit->setVisible(false);
1934 sliderPoolLimit->setVisible(false);
1935 }
1936
1937 SliderAndSpinBoxSync *sync1 =
1938 new SliderAndSpinBoxSync(sliderMemoryLimit,
1939 intMemoryLimit,
1940 getTotalRAM);
1941
1942 sync1->slotParentValueChanged();
1943 m_syncs << sync1;
1944
1945 SliderAndSpinBoxSync *sync2 =
1946 new SliderAndSpinBoxSync(sliderPoolLimit,
1947 intPoolLimit,
1948 std::bind(&KisIntParseSpinBox::value,
1949 intMemoryLimit));
1950
1951
1952 connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync2, SLOT(slotParentValueChanged()));
1953 sync2->slotParentValueChanged();
1954 m_syncs << sync2;
1955
1956 SliderAndSpinBoxSync *sync3 =
1957 new SliderAndSpinBoxSync(sliderUndoLimit,
1958 intUndoLimit,
1960 this));
1961
1962
1963 connect(intPoolLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged()));
1964 connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged()));
1965 sync3->slotParentValueChanged();
1966 m_syncs << sync3;
1967
1968 sliderSwapSize->setSuffix(i18n(" GiB"));
1969 sliderSwapSize->setRange(1, 64);
1970 intSwapSize->setRange(1, 64);
1971
1972
1973 KisAcyclicSignalConnector *swapSizeConnector = new KisAcyclicSignalConnector(this);
1974
1975 swapSizeConnector->connectForwardInt(sliderSwapSize, SIGNAL(valueChanged(int)),
1976 intSwapSize, SLOT(setValue(int)));
1977
1978 swapSizeConnector->connectBackwardInt(intSwapSize, SIGNAL(valueChanged(int)),
1979 sliderSwapSize, SLOT(setValue(int)));
1980
1981 swapFileLocation->setMode(KoFileDialog::OpenDirectory);
1982 swapFileLocation->setConfigurationName("swapfile_location");
1983 swapFileLocation->setFileName(cfg.swapDir());
1984
1985 sliderThreadsLimit->setRange(1, QThread::idealThreadCount());
1986 sliderFrameClonesLimit->setRange(1, QThread::idealThreadCount());
1987
1988 sliderFrameTimeout->setRange(5, 600);
1989 sliderFrameTimeout->setSuffix(i18nc("suffix for \"seconds\"", " sec"));
1990 sliderFrameTimeout->setValue(cfg.frameRenderingTimeout() / 1000);
1991
1992 sliderFpsLimit->setSuffix(i18n(" fps"));
1993
1994 KisWidgetConnectionUtils::connectControlState(sliderFpsLimit, m_frameRateModel.data(), "frameRateState", "frameRate");
1995 KisWidgetConnectionUtils::connectControl(chkDetectFps, m_frameRateModel.data(), "detectFrameRate");
1996
1997 connect(sliderThreadsLimit, SIGNAL(valueChanged(int)), SLOT(slotThreadsLimitChanged(int)));
1998 connect(sliderFrameClonesLimit, SIGNAL(valueChanged(int)), SLOT(slotFrameClonesLimitChanged(int)));
1999
2000 intCachedFramesSizeLimit->setRange(256, 10000);
2001 intCachedFramesSizeLimit->setSuffix(i18n(" px"));
2002 intCachedFramesSizeLimit->setSingleStep(1);
2003 intCachedFramesSizeLimit->setPageStep(1000);
2004
2005 intRegionOfInterestMargin->setRange(1, 100);
2006 KisSpinBoxI18nHelper::setText(intRegionOfInterestMargin,
2007 i18nc("{n} is the number value, % is the percent sign", "{n}%"));
2008 intRegionOfInterestMargin->setSingleStep(1);
2009 intRegionOfInterestMargin->setPageStep(10);
2010
2011 connect(chkCachedFramesSizeLimit, SIGNAL(toggled(bool)), intCachedFramesSizeLimit, SLOT(setEnabled(bool)));
2012 connect(chkUseRegionOfInterest, SIGNAL(toggled(bool)), intRegionOfInterestMargin, SLOT(setEnabled(bool)));
2013
2014 connect(chkTransformToolUseInStackPreview, SIGNAL(toggled(bool)), chkTransformToolForceLodMode, SLOT(setEnabled(bool)));
2015
2016#ifndef Q_OS_WIN
2017 // AVX workaround is needed on Windows+GCC only
2018 chkDisableAVXOptimizations->setVisible(false);
2019#endif
2020
2021 load(false);
2022}
2023
2025{
2026 qDeleteAll(m_syncs);
2027}
2028
2029void PerformanceTab::load(bool requestDefault)
2030{
2031 KisImageConfig cfg(true);
2032
2033 sliderMemoryLimit->setValue(cfg.memoryHardLimitPercent(requestDefault));
2034 sliderPoolLimit->setValue(cfg.memoryPoolLimitPercent(requestDefault));
2035 sliderUndoLimit->setValue(cfg.memorySoftLimitPercent(requestDefault));
2036
2037 chkPerformanceLogging->setChecked(cfg.enablePerfLog(requestDefault));
2038 chkProgressReporting->setChecked(cfg.enableProgressReporting(requestDefault));
2039
2040 sliderSwapSize->setValue(cfg.maxSwapSize(requestDefault) / 1024);
2041 swapFileLocation->setFileName(cfg.swapDir(requestDefault));
2042
2043 m_lastUsedThreadsLimit = cfg.maxNumberOfThreads(requestDefault);
2044 m_lastUsedClonesLimit = cfg.frameRenderingClones(requestDefault);
2045
2046 sliderThreadsLimit->setValue(m_lastUsedThreadsLimit);
2047 sliderFrameClonesLimit->setValue(m_lastUsedClonesLimit);
2048
2049#if KRITA_QT_HAS_UPDATE_COMPRESSION_PATCH
2050 m_frameRateModel->data.set(std::make_tuple(cfg.detectFpsLimit(requestDefault), cfg.fpsLimit(requestDefault)));
2051#else
2052 m_frameRateModel->data.set(std::make_tuple(false, cfg.fpsLimit(requestDefault)));
2053 chkDetectFps->setVisible(false);
2054#endif
2055 {
2056 KisConfig cfg2(true);
2057 chkOpenGLFramerateLogging->setChecked(cfg2.enableOpenGLFramerateLogging(requestDefault));
2058 chkBrushSpeedLogging->setChecked(cfg2.enableBrushSpeedLogging(requestDefault));
2059 chkDisableVectorOptimizations->setChecked(cfg2.disableVectorOptimizations(requestDefault));
2060#ifdef Q_OS_WIN
2061 chkDisableAVXOptimizations->setChecked(cfg2.disableAVXOptimizations(requestDefault));
2062#endif
2063 chkBackgroundCacheGeneration->setChecked(cfg2.calculateAnimationCacheInBackground(requestDefault));
2064 }
2065
2066 if (cfg.useOnDiskAnimationCacheSwapping(requestDefault)) {
2067 optOnDisk->setChecked(true);
2068 } else {
2069 optInMemory->setChecked(true);
2070 }
2071
2072 chkCachedFramesSizeLimit->setChecked(cfg.useAnimationCacheFrameSizeLimit(requestDefault));
2073 intCachedFramesSizeLimit->setValue(cfg.animationCacheFrameSizeLimit(requestDefault));
2074 intCachedFramesSizeLimit->setEnabled(chkCachedFramesSizeLimit->isChecked());
2075
2076 chkUseRegionOfInterest->setChecked(cfg.useAnimationCacheRegionOfInterest(requestDefault));
2077 intRegionOfInterestMargin->setValue(cfg.animationCacheRegionOfInterestMargin(requestDefault) * 100.0);
2078 intRegionOfInterestMargin->setEnabled(chkUseRegionOfInterest->isChecked());
2079
2080 {
2081 KConfigGroup group = KSharedConfig::openConfig()->group("KisToolTransform");
2082 chkTransformToolUseInStackPreview->setChecked(!group.readEntry("useOverlayPreviewStyle", false));
2083 chkTransformToolForceLodMode->setChecked(group.readEntry("forceLodMode", true));
2084 chkTransformToolForceLodMode->setEnabled(chkTransformToolUseInStackPreview->isChecked());
2085 }
2086
2087 {
2088 KConfigGroup group = KSharedConfig::openConfig()->group("KritaTransform/KisToolMove");
2089 chkMoveToolForceLodMode->setChecked(group.readEntry("forceLodMode", false));
2090 }
2091
2092 {
2093 KConfigGroup group( KSharedConfig::openConfig(), "filterdialog");
2094 chkFiltersForceLodMode->setChecked(group.readEntry("forceLodMode", true));
2095 }
2096}
2097
2099{
2100 KisImageConfig cfg(false);
2101
2102 cfg.setMemoryHardLimitPercent(sliderMemoryLimit->value());
2103 cfg.setMemorySoftLimitPercent(sliderUndoLimit->value());
2104 cfg.setMemoryPoolLimitPercent(sliderPoolLimit->value());
2105
2106 cfg.setEnablePerfLog(chkPerformanceLogging->isChecked());
2107 cfg.setEnableProgressReporting(chkProgressReporting->isChecked());
2108
2109 cfg.setMaxSwapSize(sliderSwapSize->value() * 1024);
2110
2111 cfg.setSwapDir(swapFileLocation->fileName());
2112
2113 cfg.setMaxNumberOfThreads(sliderThreadsLimit->value());
2114 cfg.setFrameRenderingClones(sliderFrameClonesLimit->value());
2115 cfg.setFrameRenderingTimeout(sliderFrameTimeout->value() * 1000);
2116 cfg.setFpsLimit(std::get<int>(*m_frameRateModel->data));
2117#if KRITA_QT_HAS_UPDATE_COMPRESSION_PATCH
2118 cfg.setDetectFpsLimit(std::get<bool>(*m_frameRateModel->data));
2119#endif
2120
2121 {
2122 KisConfig cfg2(true);
2123 cfg2.setEnableOpenGLFramerateLogging(chkOpenGLFramerateLogging->isChecked());
2124 cfg2.setEnableBrushSpeedLogging(chkBrushSpeedLogging->isChecked());
2125 cfg2.setDisableVectorOptimizations(chkDisableVectorOptimizations->isChecked());
2126#ifdef Q_OS_WIN
2127 cfg2.setDisableAVXOptimizations(chkDisableAVXOptimizations->isChecked());
2128#endif
2129 cfg2.setCalculateAnimationCacheInBackground(chkBackgroundCacheGeneration->isChecked());
2130 }
2131
2132 cfg.setUseOnDiskAnimationCacheSwapping(optOnDisk->isChecked());
2133
2134 cfg.setUseAnimationCacheFrameSizeLimit(chkCachedFramesSizeLimit->isChecked());
2135 cfg.setAnimationCacheFrameSizeLimit(intCachedFramesSizeLimit->value());
2136
2137 cfg.setUseAnimationCacheRegionOfInterest(chkUseRegionOfInterest->isChecked());
2138 cfg.setAnimationCacheRegionOfInterestMargin(intRegionOfInterestMargin->value() / 100.0);
2139
2140 {
2141 KConfigGroup group = KSharedConfig::openConfig()->group("KisToolTransform");
2142 group.writeEntry("useOverlayPreviewStyle", !chkTransformToolUseInStackPreview->isChecked());
2143 group.writeEntry("forceLodMode", chkTransformToolForceLodMode->isChecked());
2144 }
2145
2146 {
2147 KConfigGroup group = KSharedConfig::openConfig()->group("KritaTransform/KisToolMove");
2148 group.writeEntry("forceLodMode", chkMoveToolForceLodMode->isChecked());
2149 }
2150
2151 {
2152 KConfigGroup group( KSharedConfig::openConfig(), "filterdialog");
2153 group.writeEntry("forceLodMode", chkFiltersForceLodMode->isChecked());
2154 }
2155
2156}
2157
2159{
2160 KisSignalsBlocker b(sliderFrameClonesLimit);
2161 sliderFrameClonesLimit->setValue(qMin(m_lastUsedClonesLimit, value));
2163}
2164
2166{
2167 KisSignalsBlocker b(sliderThreadsLimit);
2168 sliderThreadsLimit->setValue(qMax(m_lastUsedThreadsLimit, value));
2170}
2171
2172//---------------------------------------------------------------------------------------------------
2173
2174#include "KoColor.h"
2177#include <QOpenGLContext>
2178#include <QScreen>
2179
2180namespace {
2181
2182QString colorSpaceString(const KisSurfaceColorSpaceWrapper &cs, int depth)
2183{
2184 const QString csString =
2185#ifdef HAVE_HDR
2187 cs == KisSurfaceColorSpaceWrapper::scRGBColorSpace ? "Rec. 709 Linear" :
2188#endif
2191 "Unknown Color Space";
2192
2193 return QString("%1 (%2 bit)").arg(csString).arg(depth);
2194}
2195
2196int formatToIndex(KisConfig::RootSurfaceFormat fmt)
2197{
2198 return fmt == KisConfig::BT2020_PQ ? 1 :
2199 fmt == KisConfig::BT709_G10 ? 2 :
2200 0;
2201}
2202
2203KisConfig::RootSurfaceFormat indexToFormat(int value)
2204{
2205 return value == 1 ? KisConfig::BT2020_PQ :
2208}
2209
2210int assistantDrawModeToIndex(KisConfig::AssistantsDrawMode mode)
2211{
2214 0;
2215}
2216
2217KisConfig::AssistantsDrawMode indexToAssistantDrawMode(int value)
2218{
2222}
2223
2224} // anonymous namespace
2225
2226DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name)
2227 : WdgDisplaySettings(parent, name)
2228{
2229 KisConfig cfg(true);
2230
2231 const QString rendererOpenGLText = i18nc("canvas renderer", "OpenGL");
2232 const QString rendererSoftwareText = i18nc("canvas renderer", "Software Renderer (very slow)");
2233#ifdef Q_OS_WIN
2234 const QString rendererOpenGLESText =
2235 qEnvironmentVariable("QT_ANGLE_PLATFORM") != "opengl"
2236 ? i18nc("canvas renderer", "Direct3D 11 via ANGLE")
2237 : i18nc("canvas renderer", "OpenGL via ANGLE");
2238#else
2239 const QString rendererOpenGLESText = i18nc("canvas renderer", "OpenGL ES");
2240#endif
2241
2243 lblCurrentRenderer->setText(renderer == KisOpenGL::RendererOpenGLES ? rendererOpenGLESText :
2244 renderer == KisOpenGL::RendererDesktopGL ? rendererOpenGLText :
2245 renderer == KisOpenGL::RendererSoftware ? rendererSoftwareText :
2246 i18nc("canvas renderer", "Unknown"));
2247
2248 cmbPreferredRenderer->clear();
2249
2250 const KisOpenGL::OpenGLRenderers supportedRenderers = KisOpenGL::getSupportedOpenGLRenderers();
2251 const bool onlyOneRendererSupported =
2252 supportedRenderers == KisOpenGL::RendererDesktopGL ||
2253 supportedRenderers == KisOpenGL::RendererOpenGLES ||
2254 supportedRenderers == KisOpenGL::RendererSoftware;
2255
2256
2257 if (!onlyOneRendererSupported) {
2258 QString qtPreferredRendererText;
2260 qtPreferredRendererText = rendererOpenGLESText;
2262 qtPreferredRendererText = rendererSoftwareText;
2263 } else {
2264 qtPreferredRendererText = rendererOpenGLText;
2265 }
2266 cmbPreferredRenderer->addItem(i18nc("canvas renderer", "Auto (%1)", qtPreferredRendererText), KisOpenGL::RendererAuto);
2267 cmbPreferredRenderer->setCurrentIndex(0);
2268 } else {
2269 cmbPreferredRenderer->setEnabled(false);
2270 }
2271
2272 if (supportedRenderers & KisOpenGL::RendererDesktopGL) {
2273 cmbPreferredRenderer->addItem(rendererOpenGLText, KisOpenGL::RendererDesktopGL);
2275 cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1);
2276 }
2277 }
2278
2279 if (supportedRenderers & KisOpenGL::RendererOpenGLES) {
2280 cmbPreferredRenderer->addItem(rendererOpenGLESText, KisOpenGL::RendererOpenGLES);
2282 cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1);
2283 }
2284 }
2285
2286 if (supportedRenderers & KisOpenGL::RendererSoftware) {
2287 cmbPreferredRenderer->addItem(rendererSoftwareText, KisOpenGL::RendererSoftware);
2289 cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1);
2290 }
2291 }
2292
2293 if (!(supportedRenderers &
2297
2298 grpOpenGL->setEnabled(false);
2299 grpOpenGL->setChecked(false);
2300 chkUseTextureBuffer->setEnabled(false);
2301 cmbAssistantsDrawMode->setEnabled(false);
2302 cmbFilterMode->setEnabled(false);
2303 } else {
2304 grpOpenGL->setEnabled(true);
2305 grpOpenGL->setChecked(cfg.useOpenGL());
2306 chkUseTextureBuffer->setEnabled(cfg.useOpenGL());
2307 chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer());
2308 cmbAssistantsDrawMode->setEnabled(cfg.useOpenGL());
2309 cmbAssistantsDrawMode->setCurrentIndex(assistantDrawModeToIndex(cfg.assistantsDrawMode()));
2310 cmbFilterMode->setEnabled(cfg.useOpenGL());
2311 cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode());
2312 // Don't show the high quality filtering mode if it's not available
2313 if (!KisOpenGL::supportsLoD()) {
2314 cmbFilterMode->removeItem(3);
2315 }
2316 }
2317
2318 {
2319 std::optional<KisOpenGL::XcbGLProviderProtocol> currentXcbGlProvider = KisOpenGL::xcbGlProviderProtocol();
2320
2321 lblPreferredXcbGlApi->setVisible(currentXcbGlProvider.has_value());
2322 cmbPreferredXcbGlApi->setVisible(currentXcbGlProvider.has_value());
2323
2324 if (currentXcbGlProvider.has_value()) {
2325 const QString glxCurrent = i18nc("@item:inlistbox", "GLX (current)");
2326 const QString glxNotCurrent = i18nc("@item:inlistbox", "GLX");
2327 const QString eglCurrent = i18nc("@item:inlistbox", "EGL (current)");
2328 const QString eglNotCurrent = i18nc("@item:inlistbox", "EGL");
2329
2330 cmbPreferredXcbGlApi->addItem(*currentXcbGlProvider == KisOpenGL::XCB_GLX ? glxCurrent : glxNotCurrent, KisOpenGL::XCB_GLX);
2331 cmbPreferredXcbGlApi->addItem(*currentXcbGlProvider == KisOpenGL::XCB_EGL ? eglCurrent : eglNotCurrent, KisOpenGL::XCB_EGL);
2332
2333 cmbPreferredXcbGlApi->setToolTip(i18nc("@info:tooltip",
2334 "<p>If you are using Krita on X11 or XWayland and experience slowness, "
2335 "try switching between EGL and GLX</p>"));
2336
2337 KisOpenGL::XcbGLProviderProtocol preferredValue =
2339
2340 int index = cmbPreferredXcbGlApi->findData(preferredValue);
2341
2342 KIS_SAFE_ASSERT_RECOVER(index >= 0) {
2343 index = 0;
2344 }
2345 cmbPreferredXcbGlApi->setCurrentIndex(index);
2346 }
2347 }
2348
2349 lblCurrentDisplayFormat->setText("");
2350 lblCurrentRootSurfaceFormat->setText("");
2351 grpHDRWarning->setVisible(false);
2352 cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(KisSurfaceColorSpaceWrapper::sRGBColorSpace, 8));
2353#ifdef HAVE_HDR
2354 cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(KisSurfaceColorSpaceWrapper::bt2020PQColorSpace, 10));
2355 cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(KisSurfaceColorSpaceWrapper::scRGBColorSpace, 16));
2356#endif
2357 cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(KisConfig::BT709_G22));
2358 slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex());
2359
2360 QOpenGLContext *context = QOpenGLContext::currentContext();
2361
2362 if (!context) {
2363 context = QOpenGLContext::globalShareContext();
2364 }
2365
2366 if (context) {
2367 QScreen *screen = KisPart::instance()->currentMainwindow()->screen();
2368 KisScreenInformationAdapter adapter(context);
2369 if (screen && adapter.isValid()) {
2371 if (info.isValid()) {
2372 QStringList toolTip;
2373
2374 toolTip << i18n("Display Id: %1", info.screen->name());
2375 toolTip << i18n("Display Name: %1 %2", info.screen->manufacturer(), info.screen->model());
2376 toolTip << i18n("Min Luminance: %1", info.minLuminance);
2377 toolTip << i18n("Max Luminance: %1", info.maxLuminance);
2378 toolTip << i18n("Max Full Frame Luminance: %1", info.maxFullFrameLuminance);
2379 toolTip << i18n("Red Primary: %1, %2", info.redPrimary[0], info.redPrimary[1]);
2380 toolTip << i18n("Green Primary: %1, %2", info.greenPrimary[0], info.greenPrimary[1]);
2381 toolTip << i18n("Blue Primary: %1, %2", info.bluePrimary[0], info.bluePrimary[1]);
2382 toolTip << i18n("White Point: %1, %2", info.whitePoint[0], info.whitePoint[1]);
2383
2384 lblCurrentDisplayFormat->setToolTip(toolTip.join('\n'));
2385 lblCurrentDisplayFormat->setText(colorSpaceString(info.colorSpace, info.bitsPerColor));
2386 } else {
2387 lblCurrentDisplayFormat->setToolTip("");
2388 lblCurrentDisplayFormat->setText(i18n("Unknown"));
2389 }
2390 } else {
2391 lblCurrentDisplayFormat->setToolTip("");
2392 lblCurrentDisplayFormat->setText(i18n("Unknown"));
2393 qWarning() << "Failed to fetch display info:" << adapter.errorString();
2394 }
2395
2396 const QSurfaceFormat currentFormat = KisOpenGLModeProber::instance()->surfaceformatInUse();
2397 const auto colorSpace = KisSurfaceColorSpaceWrapper::fromQtColorSpace(currentFormat.colorSpace());
2398 lblCurrentRootSurfaceFormat->setText(colorSpaceString(colorSpace, currentFormat.redBufferSize()));
2399 cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(cfg.rootSurfaceFormat()));
2400 connect(cmbPreferedRootSurfaceFormat, SIGNAL(currentIndexChanged(int)), SLOT(slotPreferredSurfaceFormatChanged(int)));
2401 slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex());
2402 }
2403
2404#ifndef HAVE_HDR
2405 HDR->setEnabled(false);
2406
2412 if (KisPlatformPluginInterfaceFactory::instance()->surfaceColorManagedByOS()) {
2413 const int hdrTabIndex = tabWidget->indexOf(HDR);
2414 KIS_SAFE_ASSERT_RECOVER_NOOP(hdrTabIndex >= 0);
2415 if (hdrTabIndex >= 0) {
2416 tabWidget->setTabVisible(hdrTabIndex, false);
2417 }
2418 }
2419#endif
2420
2421 const QStringList openglWarnings = KisOpenGL::getOpenGLWarnings();
2422 if (openglWarnings.isEmpty()) {
2423 grpOpenGLWarnings->setVisible(false);
2424 } else {
2425 QString text = QString("<p><b>%1</b>").arg(i18n("Warning(s):"));
2426 text.append("<ul>");
2427 Q_FOREACH (const QString &warning, openglWarnings) {
2428 text.append("<li>");
2429 text.append(warning.toHtmlEscaped());
2430 text.append("</li>");
2431 }
2432 text.append("</ul></p>");
2433 grpOpenGLWarnings->setText(text);
2434 grpOpenGLWarnings->setPixmap(
2435 grpOpenGLWarnings->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
2436 grpOpenGLWarnings->setVisible(true);
2437 }
2438
2439 KisImageConfig imageCfg(false);
2440
2441 KoColor c;
2443 c.setOpacity(1.0);
2444 btnSelectionOverlayColor->setColor(c);
2445 sldSelectionOverlayOpacity->setRange(0.0, 1.0, 2);
2446 sldSelectionOverlayOpacity->setSingleStep(0.05);
2447 sldSelectionOverlayOpacity->setValue(imageCfg.selectionOverlayMaskColor().alphaF());
2448
2449 sldSelectionOutlineOpacity->setRange(0.0, 1.0, 2);
2450 sldSelectionOutlineOpacity->setSingleStep(0.05);
2451 sldSelectionOutlineOpacity->setValue(imageCfg.selectionOutlineOpacity());
2452
2453 intCheckSize->setValue(cfg.checkSize());
2454 chkMoving->setChecked(cfg.scrollCheckers());
2456 ck1.fromQColor(cfg.checkersColor1());
2457 colorChecks1->setColor(ck1);
2459 ck2.fromQColor(cfg.checkersColor2());
2460 colorChecks2->setColor(ck2);
2462 cb.fromQColor(cfg.canvasBorderColor());
2463 canvasBorder->setColor(cb);
2464 hideScrollbars->setChecked(cfg.hideScrollbars());
2465 chkCurveAntialiasing->setChecked(cfg.antialiasCurves());
2466 chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline());
2467 chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor());
2468 chkHidePopups->setChecked(cfg.hidePopups());
2469
2470 connect(grpOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool)));
2471
2472 KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8());
2473 gridColor.fromQColor(cfg.getPixelGridColor());
2474 pixelGridColorButton->setColor(gridColor);
2475 pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold() * 100);
2476 KisSpinBoxI18nHelper::setText(pixelGridDrawingThresholdBox, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
2477}
2478
2480{
2481 KisConfig cfg(true);
2482 cmbPreferredRenderer->setCurrentIndex(0);
2485 grpOpenGL->setEnabled(false);
2486 grpOpenGL->setChecked(false);
2487 chkUseTextureBuffer->setEnabled(false);
2488 cmbAssistantsDrawMode->setEnabled(false);
2489 cmbFilterMode->setEnabled(false);
2490 }
2491 else {
2492 grpOpenGL->setEnabled(true);
2493 grpOpenGL->setChecked(cfg.useOpenGL(true));
2494 chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer(true));
2495 chkUseTextureBuffer->setEnabled(true);
2496 cmbAssistantsDrawMode->setEnabled(true);
2497 cmbAssistantsDrawMode->setCurrentIndex(assistantDrawModeToIndex(cfg.assistantsDrawMode(true)));
2498 cmbFilterMode->setEnabled(true);
2499 cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode(true));
2500 }
2501
2502 chkMoving->setChecked(cfg.scrollCheckers(true));
2503
2504 KisImageConfig imageCfg(false);
2505
2506 KoColor c;
2507 c.fromQColor(imageCfg.selectionOverlayMaskColor(true));
2508 c.setOpacity(1.0);
2509 btnSelectionOverlayColor->setColor(c);
2510 sldSelectionOverlayOpacity->setValue(imageCfg.selectionOverlayMaskColor(true).alphaF());
2511
2512 sldSelectionOutlineOpacity->setValue(imageCfg.selectionOutlineOpacity(true));
2513
2514 intCheckSize->setValue(cfg.checkSize(true));
2516 ck1.fromQColor(cfg.checkersColor1(true));
2517 colorChecks1->setColor(ck1);
2519 ck2.fromQColor(cfg.checkersColor2(true));
2520 colorChecks2->setColor(ck2);
2522 cvb.fromQColor(cfg.canvasBorderColor(true));
2523 canvasBorder->setColor(cvb);
2524 hideScrollbars->setChecked(cfg.hideScrollbars(true));
2525 chkCurveAntialiasing->setChecked(cfg.antialiasCurves(true));
2526 chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline(true));
2527 chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor(true));
2528 chkHidePopups->setChecked(cfg.hidePopups(true));
2529
2530 KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8());
2531 gridColor.fromQColor(cfg.getPixelGridColor(true));
2532 pixelGridColorButton->setColor(gridColor);
2533 pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold(true) * 100);
2534 KisSpinBoxI18nHelper::setText(pixelGridDrawingThresholdBox, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
2535
2536 cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(KisConfig::BT709_G22));
2537 slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex());
2538}
2539
2541{
2542 chkUseTextureBuffer->setEnabled(isChecked);
2543 cmbFilterMode->setEnabled(isChecked);
2544 cmbAssistantsDrawMode->setEnabled(isChecked);
2545}
2546
2548{
2549 Q_UNUSED(index);
2550
2551 QOpenGLContext *context = QOpenGLContext::currentContext();
2552 if (context) {
2553 QScreen *screen = KisPart::instance()->currentMainwindow()->screen();
2554 KisScreenInformationAdapter adapter(context);
2555 if (adapter.isValid()) {
2557 if (info.isValid()) {
2558 if (cmbPreferedRootSurfaceFormat->currentIndex() != formatToIndex(KisConfig::BT709_G22) &&
2560 grpHDRWarning->setVisible(true);
2561 grpHDRWarning->setPixmap(
2562 grpHDRWarning->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
2563 grpHDRWarning->setText(i18n("<b>Warning:</b> current display doesn't support HDR rendering"));
2564 } else {
2565 grpHDRWarning->setVisible(false);
2566 }
2567 }
2568 }
2569 }
2570}
2571
2572//---------------------------------------------------------------------------------------------------
2574{
2575 KisConfig cfg(true);
2576
2577 chkDockers->setChecked(cfg.hideDockersFullscreen());
2578 chkMenu->setChecked(cfg.hideMenuFullscreen());
2579 chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen());
2580 chkStatusbar->setChecked(cfg.hideStatusbarFullscreen());
2581 chkTitlebar->setChecked(cfg.hideTitlebarFullscreen());
2582 chkToolbar->setChecked(cfg.hideToolbarFullscreen());
2583
2584}
2585
2587{
2588 KisConfig cfg(true);
2589 chkDockers->setChecked(cfg.hideDockersFullscreen(true));
2590 chkMenu->setChecked(cfg.hideMenuFullscreen(true));
2591 chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen(true));
2592 chkStatusbar->setChecked(cfg.hideStatusbarFullscreen(true));
2593 chkTitlebar->setChecked(cfg.hideTitlebarFullscreen(true));
2594 chkToolbar->setChecked(cfg.hideToolbarFullscreen(true));
2595}
2596
2597
2598//---------------------------------------------------------------------------------------------------
2599
2601static const QStringList allowedColorHistorySortingValues({"none", "hsv"});
2602}
2603
2604PopupPaletteTab::PopupPaletteTab(QWidget *parent, const char *name)
2605 : WdgPopupPaletteSettingsBase(parent, name)
2606{
2607 using namespace PopupPaletteTabPrivate;
2608
2609 load();
2610
2611 connect(chkShowColorHistory, SIGNAL(toggled(bool)), cmbColorHistorySorting, SLOT(setEnabled(bool)));
2612 connect(chkShowColorHistory, SIGNAL(toggled(bool)), lblColorHistorySorting, SLOT(setEnabled(bool)));
2613 connect(cmbSelectorType, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSelectorTypeChanged(int)));
2614 KIS_SAFE_ASSERT_RECOVER_NOOP(cmbColorHistorySorting->count() == allowedColorHistorySortingValues.size());
2615}
2616
2618{
2619 using namespace PopupPaletteTabPrivate;
2620
2621 KisConfig config(true);
2622 sbNumPresets->setValue(config.favoritePresets());
2623 sbPaletteSize->setValue(config.readEntry("popuppalette/size", 385));
2624 sbSelectorSize->setValue(config.readEntry("popuppalette/selectorSize", 140));
2625 cmbSelectorType->setCurrentIndex(config.readEntry<bool>("popuppalette/usevisualcolorselector", false) ? 1 : 0);
2626 chkShowColorHistory->setChecked(config.readEntry("popuppalette/showColorHistory", true));
2627 chkShowRotationTrack->setChecked(config.readEntry("popuppalette/showRotationTrack", true));
2628 chkUseDynamicSlotCount->setChecked(config.readEntry("popuppalette/useDynamicSlotCount", true));
2629 grpFixTriangleRotation->setChecked(config.readEntry("popuppalette/fixTriangleRotation", false));
2630 sbTriangleRotationAngle->setValue(config.readEntry("popuppalette/triangleRotationAngle", 0));
2631
2632 QString currentSorting = config.readEntry("popuppalette/colorHistorySorting", QString("hsv"));
2633 if (!allowedColorHistorySortingValues.contains(currentSorting)) {
2634 currentSorting = "hsv";
2635 }
2636 cmbColorHistorySorting->setCurrentIndex(allowedColorHistorySortingValues.indexOf(currentSorting));
2637 cmbColorHistorySorting->setEnabled(chkShowColorHistory->isChecked());
2638 lblColorHistorySorting->setEnabled(chkShowColorHistory->isChecked());
2639 grpFixTriangleRotation->setEnabled(!cmbSelectorType->currentIndex());
2640}
2641
2643{
2644 using namespace PopupPaletteTabPrivate;
2645
2646 KisConfig config(true);
2647 config.setFavoritePresets(sbNumPresets->value());
2648 config.writeEntry("popuppalette/size", sbPaletteSize->value());
2649 config.writeEntry("popuppalette/selectorSize", sbSelectorSize->value());
2650 config.writeEntry<bool>("popuppalette/usevisualcolorselector", cmbSelectorType->currentIndex() > 0);
2651 config.writeEntry<bool>("popuppalette/showColorHistory", chkShowColorHistory->isChecked());
2652 config.writeEntry<bool>("popuppalette/showRotationTrack", chkShowRotationTrack->isChecked());
2653 config.writeEntry<bool>("popuppalette/useDynamicSlotCount", chkUseDynamicSlotCount->isChecked());
2654 config.writeEntry("popuppalette/colorHistorySorting",
2655 allowedColorHistorySortingValues[cmbColorHistorySorting->currentIndex()]);
2656 config.writeEntry<bool>("popuppalette/fixTriangleRotation", grpFixTriangleRotation->isChecked());
2657 config.writeEntry("popuppalette/triangleRotationAngle", sbTriangleRotationAngle->value());
2658}
2659
2661{
2662 KisConfig config(true);
2663 sbNumPresets->setValue(config.favoritePresets(true));
2664 sbPaletteSize->setValue(385);
2665 sbSelectorSize->setValue(140);
2666 cmbSelectorType->setCurrentIndex(0);
2667 chkShowColorHistory->setChecked(true);
2668 chkShowRotationTrack->setChecked(true);
2669 chkUseDynamicSlotCount->setChecked(true);
2670 cmbColorHistorySorting->setEnabled(chkShowColorHistory->isChecked());
2671 lblColorHistorySorting->setEnabled(chkShowColorHistory->isChecked());
2672 grpFixTriangleRotation->setChecked(false);
2673 sbTriangleRotationAngle->setValue(0);
2674}
2675
2677 grpFixTriangleRotation->setEnabled(!index);
2678}
2679
2680//---------------------------------------------------------------------------------------------------
2681
2682KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name)
2683 : KPageDialog(parent)
2684{
2685 Q_UNUSED(name);
2686 setWindowTitle(i18n("Configure Krita"));
2687 setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults);
2688
2689 setFaceType(KPageDialog::List);
2690
2691 // General
2692 KoVBox *vbox = new KoVBox();
2693 KPageWidgetItem *page = new KPageWidgetItem(vbox, i18n("General"));
2694 page->setObjectName("general");
2695 page->setHeader(i18n("General"));
2696 page->setIcon(KisIconUtils::loadIcon("config-general"));
2697 m_pages << page;
2698 addPage(page);
2699 m_general = new GeneralTab(vbox);
2700
2701 // Shortcuts
2702 vbox = new KoVBox();
2703 page = new KPageWidgetItem(vbox, i18n("Keyboard Shortcuts"));
2704 page->setObjectName("shortcuts");
2705 page->setHeader(i18n("Shortcuts"));
2706 page->setIcon(KisIconUtils::loadIcon("config-keyboard"));
2707 m_pages << page;
2708 addPage(page);
2710 connect(this, SIGNAL(accepted()), m_shortcutSettings, SLOT(saveChanges()));
2711 connect(this, SIGNAL(rejected()), m_shortcutSettings, SLOT(cancelChanges()));
2712
2713 // Canvas input settings
2715 page = addPage(m_inputConfiguration, i18n("Canvas Input Settings"));
2716 page->setHeader(i18n("Canvas Input"));
2717 page->setObjectName("canvasinput");
2718 page->setIcon(KisIconUtils::loadIcon("config-canvas-input"));
2719 m_pages << page;
2720
2721 // Display
2722 vbox = new KoVBox();
2723 page = new KPageWidgetItem(vbox, i18n("Display"));
2724 page->setObjectName("display");
2725 page->setHeader(i18n("Display"));
2726 page->setIcon(KisIconUtils::loadIcon("config-display"));
2727 m_pages << page;
2728 addPage(page);
2730
2731 // Color
2732 vbox = new KoVBox();
2733 page = new KPageWidgetItem(vbox, i18n("Color Management"));
2734 page->setObjectName("colormanagement");
2735 page->setHeader(i18nc("Label of color as in Color Management", "Color"));
2736 page->setIcon(KisIconUtils::loadIcon("config-color-manage"));
2737 m_pages << page;
2738 addPage(page);
2740
2741 // Performance
2742 vbox = new KoVBox();
2743 page = new KPageWidgetItem(vbox, i18n("Performance"));
2744 page->setObjectName("performance");
2745 page->setHeader(i18n("Performance"));
2746 page->setIcon(KisIconUtils::loadIcon("config-performance"));
2747 m_pages << page;
2748 addPage(page);
2750
2751 // Tablet
2752 vbox = new KoVBox();
2753 page = new KPageWidgetItem(vbox, i18n("Tablet settings"));
2754 page->setObjectName("tablet");
2755 page->setHeader(i18n("Tablet"));
2756 page->setIcon(KisIconUtils::loadIcon("config-tablet"));
2757 m_pages << page;
2758 addPage(page);
2760
2761 // full-screen mode
2762 vbox = new KoVBox();
2763 page = new KPageWidgetItem(vbox, i18n("Canvas-only settings"));
2764 page->setObjectName("canvasonly");
2765 page->setHeader(i18n("Canvas-only"));
2766 page->setIcon(KisIconUtils::loadIcon("config-canvas-only"));
2767 m_pages << page;
2768 addPage(page);
2770
2771 // Pop-up Palette
2772 vbox = new KoVBox();
2773 page = new KPageWidgetItem(vbox, i18n("Pop-up Palette"));
2774 page->setObjectName("popuppalette");
2775 page->setHeader(i18n("Pop-up Palette"));
2776 page->setIcon(KisIconUtils::loadIcon("config-popup-palette"));
2777 m_pages << page;
2778 addPage(page);
2780
2781 // Author profiles
2783 page = addPage(m_authorPage, i18nc("@title:tab Author page", "Author" ));
2784 page->setObjectName("author");
2785 page->setHeader(i18n("Author"));
2786 page->setIcon(KisIconUtils::loadIcon("user-identity"));
2787 m_pages << page;
2788
2789 KGuiItem::assign(button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
2790 KGuiItem::assign(button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
2791 QPushButton *restoreDefaultsButton = button(QDialogButtonBox::RestoreDefaults);
2792 restoreDefaultsButton->setText(i18nc("@action:button", "Restore Defaults"));
2793
2794 connect(this, SIGNAL(accepted()), m_inputConfiguration, SLOT(saveChanges()));
2795 connect(this, SIGNAL(rejected()), m_inputConfiguration, SLOT(revertChanges()));
2796
2798 QStringList keys = preferenceSetRegistry->keys();
2799 keys.sort();
2800 Q_FOREACH(const QString &key, keys) {
2801 KisAbstractPreferenceSetFactory *preferenceSetFactory = preferenceSetRegistry->value(key);
2802 KisPreferenceSet* preferenceSet = preferenceSetFactory->createPreferenceSet();
2803 vbox = new KoVBox();
2804 page = new KPageWidgetItem(vbox, preferenceSet->name());
2805 page->setHeader(preferenceSet->header());
2806 page->setIcon(preferenceSet->icon());
2807 addPage(page);
2808 preferenceSet->setParent(vbox);
2809 preferenceSet->loadPreferences();
2810
2811 connect(restoreDefaultsButton, SIGNAL(clicked(bool)), preferenceSet, SLOT(loadDefaultPreferences()), Qt::UniqueConnection);
2812 connect(this, SIGNAL(accepted()), preferenceSet, SLOT(savePreferences()), Qt::UniqueConnection);
2813 }
2814
2815 connect(restoreDefaultsButton, SIGNAL(clicked(bool)), this, SLOT(slotDefault()));
2816
2817 KisConfig cfg(true);
2818 QString currentPageName = cfg.readEntry<QString>("KisDlgPreferences/CurrentPage");
2819 Q_FOREACH(KPageWidgetItem *page, m_pages) {
2820 if (page->objectName() == currentPageName) {
2821 setCurrentPage(page);
2822 break;
2823 }
2824 }
2825
2826 // TODO QT6: check what this code actually does?
2827#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
2828 {
2829 // HACK ALERT! Remove title widget background, thus making
2830 // it consistent across all systems
2831 const auto *titleWidget = findChild<KTitleWidget*>();
2832 if (titleWidget) {
2833 QLayoutItem *titleFrame = titleWidget->layout()->itemAt(0); // vboxLayout -> titleFrame
2834 if (titleFrame) {
2835 titleFrame->widget()->setBackgroundRole(QPalette::Window);
2836 }
2837 }
2838 }
2839#endif
2840}
2841
2843{
2844 KisConfig cfg(true);
2845 cfg.writeEntry<QString>("KisDlgPreferences/CurrentPage", currentPage()->objectName());
2846}
2847
2848void KisDlgPreferences::showEvent(QShowEvent *event){
2849 KPageDialog::showEvent(event);
2850 button(QDialogButtonBox::Cancel)->setAutoDefault(false);
2851 button(QDialogButtonBox::Ok)->setAutoDefault(false);
2852 button(QDialogButtonBox::RestoreDefaults)->setAutoDefault(false);
2853 button(QDialogButtonBox::Cancel)->setDefault(false);
2854 button(QDialogButtonBox::Ok)->setDefault(false);
2855 button(QDialogButtonBox::RestoreDefaults)->setDefault(false);
2856}
2857
2859{
2860 if (buttonBox()->buttonRole(button) == QDialogButtonBox::RejectRole) {
2861 m_cancelClicked = true;
2862 }
2863}
2864
2866{
2867 if (currentPage()->objectName() == "general") {
2869 }
2870 else if (currentPage()->objectName() == "shortcuts") {
2872 }
2873 else if (currentPage()->objectName() == "display") {
2875 }
2876 else if (currentPage()->objectName() == "colormanagement") {
2878 }
2879 else if (currentPage()->objectName() == "performance") {
2881 }
2882 else if (currentPage()->objectName() == "tablet") {
2884 }
2885 else if (currentPage()->objectName() == "canvasonly") {
2887 }
2888 else if (currentPage()->objectName() == "canvasinput") {
2890 }
2891 else if (currentPage()->objectName() == "popuppalette") {
2893 }
2894}
2895
2896KPageWidgetItem *KisDlgPreferences::getPage(Page page_enum)
2897{
2898 QString name = "";
2899 switch (page_enum) {
2900 case General:
2901 name = "general";
2902 break;
2903 case Shortucts:
2904 name = "shortcuts";
2905 break;
2906 case Color:
2907 name = "colormanagement";
2908 break;
2909 case Performance:
2910 name = "performance";
2911 break;
2912 case Display:
2913 name = "display";
2914 break;
2915 case Tablet:
2916 name = "tablet";
2917 break;
2918 case Fullscreen:
2919 name = "canvasonly";
2920 break;
2921 case Input:
2922 name = "canvasinput";
2923 break;
2924 case PopupPalette:
2925 name = "popuppalette";
2926 break;
2927 }
2928
2929 Q_FOREACH (KPageWidgetItem *page, m_pages) {
2930 if (page->objectName() == name) {
2931 return page;
2932 }
2933 }
2934 return nullptr;
2935}
2936
2938{
2939 switch (page.page) {
2940 case General: {
2941 QWidget *tab = nullptr;
2942 switch (page.tab) {
2943 case File:
2944 tab = m_general->File;
2945 break;
2946 case Pasting:
2947 tab = m_general->Pasting;
2948 break;
2949 case Window:
2950 tab = m_general->Window;
2951 break;
2952 case Cursor:
2953 tab = m_general->Cursor;
2954 break;
2955 case Tools:
2956 tab = m_general->Tools;
2957 break;
2958 case Animation:
2959 tab = m_general->Animation;
2960 break;
2961 case Resources:
2962 tab = m_general->Resources;
2963 break;
2965 tab = m_general->Miscellaneous;
2966 break;
2967 }
2968 m_general->tabWidget->setCurrentWidget(tab);
2969 } break;
2970 case Color: {
2971 QWidget *tab = nullptr;
2972 switch (page.tab) {
2973 case GeneralColor:
2974 tab = m_colorSettings->m_page->General;
2975 break;
2976 case DisplayTab:
2977 tab = m_colorSettings->m_page->Display;
2978 break;
2979 case SoftProofing:
2980 tab = m_colorSettings->m_page->SoftProofing;
2981 break;
2982 }
2983 m_colorSettings->m_page->tabWidget->setCurrentWidget(tab);
2984 } break;
2985 case Performance: {
2986 QWidget *tab = nullptr;
2987 switch (page.tab) {
2988 case GeneralPerformance:
2989 tab = m_performanceSettings->General;
2990 break;
2991 case Advanced:
2992 tab = m_performanceSettings->Advanced;
2993 break;
2994 case AnimationCache:
2995 tab = m_performanceSettings->AnimationCache;
2996 break;
2997 case InstantPreview:
2998 tab = m_performanceSettings->InstantPreview;
2999 break;
3000 }
3001 m_performanceSettings->tabWidget->setCurrentWidget(tab);
3002 } break;
3003 case Display: {
3004 QWidget *tab = nullptr;
3005 switch (page.tab) {
3006 case CanvasAcceleration:
3007 tab = m_displaySettings->CanvasAcceleration;
3008 break;
3009 case HDR:
3010 tab = m_displaySettings->HDR;
3011 break;
3012 case CanvasDecoration:
3013 tab = m_displaySettings->CanvasDecoration;
3014 break;
3016 tab = m_displaySettings->Miscellaneous;
3017 break;
3018 }
3019 m_displaySettings->tabWidget->setCurrentWidget(tab);
3020 } break;
3021
3022 default:
3023 break;
3024 }
3025}
3026
3027bool KisDlgPreferences::editPreferences(std::optional<PageDesc>page)
3028{
3029 connect(this->buttonBox(), SIGNAL(clicked(QAbstractButton*)), this, SLOT(slotButtonClicked(QAbstractButton*)));
3030
3031 if (page.has_value()) {
3032 PageDesc page_val = page.value();
3033 setCurrentPage(getPage(page_val.page));
3034 switchTab(page_val);
3035 }
3036
3037 int retval = exec();
3038 Q_UNUSED(retval);
3039
3040 if (!m_cancelClicked) {
3041 // General settings
3042 KisConfig cfg(false);
3043 KisImageConfig cfgImage(false);
3044
3047 cfg.setSeparateEraserCursor(m_general->m_chkSeparateEraserCursor->isChecked());
3055
3058 cfg.setForceAlwaysFullSizedOutline(!m_general->m_changeBrushOutline->isChecked());
3060 cfg.setForceAlwaysFullSizedEraserOutline(!m_general->m_changeEraserBrushOutline->isChecked());
3063
3064 KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs");
3065 group.writeEntry("DontUseNativeFileDialog", !m_general->m_chkNativeFileDialog->isChecked());
3066
3067 cfgImage.setMaxBrushSize(m_general->intMaxBrushSize->value());
3068 cfg.setIgnoreHighFunctionKeys(m_general->chkIgnoreHighFunctionKeys->isChecked());
3069
3070 cfg.writeEntry<bool>("use_custom_system_font", m_general->chkUseCustomFont->isChecked());
3071 if (m_general->chkUseCustomFont->isChecked()) {
3072 cfg.writeEntry<QString>("custom_system_font", m_general->cmbCustomFont->currentFont().family());
3073 cfg.writeEntry<int>("custom_font_size", m_general->intFontSize->value());
3074 }
3075 else {
3076 cfg.writeEntry<QString>("custom_system_font", "");
3077 cfg.writeEntry<int>("custom_font_size", -1);
3078 }
3079
3080 cfg.writeEntry<int>("mdi_viewmode", m_general->mdiMode());
3081 cfg.setMDIBackgroundColor(m_general->m_mdiColor->color().toXML());
3082 cfg.setMDIBackgroundImage(m_general->m_backgroundimage->text());
3083 cfg.writeEntry<int>("mdi_rubberband", m_general->m_chkRubberBand->isChecked());
3085 cfg.writeEntry("autosavefileshidden", m_general->chkHideAutosaveFiles->isChecked());
3086
3087 cfg.setBackupFile(m_general->m_backupFileCheckBox->isChecked());
3088 cfg.writeEntry("backupfilelocation", m_general->cmbBackupFileLocation->currentIndex());
3089 cfg.writeEntry("backupfilesuffix", m_general->txtBackupFileSuffix->text());
3090 cfg.writeEntry("numberofbackupfiles", m_general->intNumBackupFiles->value());
3091
3092
3100
3101 const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
3102 QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
3103 kritarc.setValue("EnableHiDPI", m_general->m_chkHiDPI->isChecked());
3104#if defined(Q_OS_WIN) && defined(HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY)
3105 kritarc.setValue("EnableHiDPIFractionalScaling", m_general->m_chkHiDPIFractionalScaling->isChecked());
3106#endif
3107 kritarc.setValue("LogUsage", m_general->chkUsageLogging->isChecked());
3108
3110
3111 cfg.writeEntry<bool>("useCreamyAlphaDarken", (bool)!m_general->cmbFlowMode->currentIndex());
3112 cfg.writeEntry<bool>("useSubtractiveBlendingForCmykColorSpaces", (bool)!m_general->cmbCmykBlendingMode->currentIndex());
3113
3120
3122
3124 cfg.setTouchPainting(KisConfig::TouchPainting(m_general->cmbTouchPainting->currentIndex()));
3125 cfg.writeEntry("useTouchPressureSensitivity", m_general->chkTouchPressureSensitivity->isChecked());
3126 cfg.setActivateTransformToolAfterPaste(m_general->chkEnableTransformToolAfterPaste->isChecked());
3127 cfg.setZoomHorizontal(m_general->chkZoomHorizontally->isChecked());
3128 cfg.setSelectionActionBar(m_general->chkEnableSelectionActionBar->isChecked());
3129
3132 cfg.setCumulativeUndoRedo(m_general->chkCumulativeUndo->isChecked());
3134
3135 // Animation..
3139
3140#ifdef Q_OS_ANDROID
3141 QFileInfo fi(m_general->m_resourceFolderSelector->currentData(Qt::UserRole).value<QString>());
3142#else
3143 QFileInfo fi(m_general->m_urlResourceFolder->fileName());
3144#endif
3145 if (fi.isWritable()) {
3147 }
3148
3152
3153 // Color settings
3155 cfg.setUseSystemMonitorProfile(m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked());
3156 for (int i = 0; i < QApplication::screens().count(); ++i) {
3157 if (m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()) {
3158 int currentIndex = m_colorSettings->m_monitorProfileWidgets[i]->currentIndex();
3159 QString monitorid = m_colorSettings->m_monitorProfileWidgets[i]->itemData(currentIndex).toString();
3160 cfg.setMonitorForScreen(i, monitorid);
3161 } else {
3162 cfg.setMonitorProfile(i,
3163 m_colorSettings->m_monitorProfileWidgets[i]->currentUnsqueezedText(),
3164 m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked());
3165 }
3166 }
3167 } else {
3171 }
3172 cfg.setUseDefaultColorSpace(m_colorSettings->m_page->useDefColorSpace->isChecked());
3173 if (cfg.useDefaultColorSpace())
3174 {
3175 KoID currentWorkingColorSpace = m_colorSettings->m_page->cmbWorkingColorSpace->currentItem();
3176 cfg.setWorkingColorSpace(currentWorkingColorSpace.id());
3177 cfg.defColorModel(KoColorSpaceRegistry::instance()->colorSpaceColorModelId(currentWorkingColorSpace.id()).id());
3178 cfg.setDefaultColorDepth(KoColorSpaceRegistry::instance()->colorSpaceColorDepthId(currentWorkingColorSpace.id()).id());
3179 }
3180
3181 cfg.writeEntry("ExrDefaultColorProfile", m_colorSettings->m_page->cmbColorProfileForEXR->currentText());
3182
3183 cfgImage.setDefaultProofingConfig(*m_colorSettings->m_page->wdgProofingOptions->currentProofingConfig());
3184 cfg.setUseBlackPointCompensation(m_colorSettings->m_page->chkBlackpoint->isChecked());
3185 cfg.setAllowLCMSOptimization(m_colorSettings->m_page->chkAllowLCMSOptimization->isChecked());
3186 cfg.setForcePaletteColors(m_colorSettings->m_page->chkForcePaletteColor->isChecked());
3188 cfg.setRenderIntent(m_colorSettings->m_page->cmbMonitorIntent->currentIndex());
3189
3190 // Tablet settings
3191 cfg.setPressureTabletCurve( m_tabletSettings->m_page->pressureCurve->curve().toString() );
3193 m_tabletSettings->m_page->chkUseRightMiddleClickWorkaround->isChecked());
3194
3195#if defined Q_OS_WIN && (defined QT5_HAS_WINTAB_SWITCH || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
3196 cfg.setUseWin8PointerInput(m_tabletSettings->m_page->radioWin8PointerInput->isChecked());
3197
3198# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
3199 // Qt6 supports switching the tablet API on the fly
3200 using QWindowsApplication = QNativeInterface::Private::QWindowsApplication;
3201 if (auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration())) {
3202 nativeWindowsApp->setWinTabEnabled(!cfg.useWin8PointerInput());
3203 }
3204# endif
3205#endif
3206 cfg.writeEntry<bool>("useTimestampsForBrushSpeed", m_tabletSettings->m_page->chkUseTimestampsForBrushSpeed->isChecked());
3207
3208#if KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_PAGE_UP_DOWN
3209 cfg.setUsePageUpDownMouseButtonEmulationWorkaround(
3210 m_tabletSettings->m_page->chkUsePageUpDownMouseButtonEmulationWorkaround->isChecked());
3211#endif
3212
3213#if KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_HIGH_FUNCTION_KEYS
3214 cfg.setUseHighFunctionKeyMouseButtonEmulationWorkaround(
3215 m_tabletSettings->m_page->chkUseHighFunctionKeyMouseButtonEmulationWorkaround->isChecked());
3216#endif
3217
3218#if KRITA_QT_HAS_ANDROID_IGNORE_HISTORIC_TABLET_EVENTS
3219 cfg.setUseIgnoreHistoricTabletEventsWorkaround(
3220 m_tabletSettings->m_page->chkUseIgnoreHistoricTabletEventsWorkaround->isChecked());
3221#endif
3222
3223 cfg.writeEntry<int>("maxAllowedSpeedValue", m_tabletSettings->m_page->intMaxAllowedBrushSpeed->value());
3224 cfg.writeEntry<int>("speedValueSmoothing", m_tabletSettings->m_page->intBrushSpeedSmoothing->value());
3225 // the angle is saved in clockwise direction to be consistent with Drawing Angle, so negate
3226 cfg.writeEntry<int>("tiltDirectionOffset", -m_tabletSettings->m_page->tiltDirectionOffsetAngle->angle());
3227
3229
3230 if (!cfg.useOpenGL() && m_displaySettings->grpOpenGL->isChecked())
3231 cfg.setCanvasState("TRY_OPENGL");
3232
3233 if (m_displaySettings->grpOpenGL->isChecked()) {
3235 m_displaySettings->cmbPreferredRenderer->itemData(
3236 m_displaySettings->cmbPreferredRenderer->currentIndex()).toInt());
3238 } else {
3240 }
3241
3242 if (KisOpenGL::xcbGlProviderProtocol().has_value()) {
3243 cfg.setPreferXcbEglProvider(m_displaySettings->cmbPreferredXcbGlApi->currentData().value<KisOpenGL::XcbGLProviderProtocol>() == KisOpenGL::XCB_EGL);
3244 }
3245
3246 cfg.setUseOpenGLTextureBuffer(m_displaySettings->chkUseTextureBuffer->isChecked());
3247 cfg.setOpenGLFilteringMode(m_displaySettings->cmbFilterMode->currentIndex());
3248 cfg.setRootSurfaceFormat(&kritarc, indexToFormat(m_displaySettings->cmbPreferedRootSurfaceFormat->currentIndex()));
3249 cfg.setAssistantsDrawMode(indexToAssistantDrawMode(m_displaySettings->cmbAssistantsDrawMode->currentIndex()));
3250
3251 cfg.setCheckSize(m_displaySettings->intCheckSize->value());
3252 cfg.setScrollingCheckers(m_displaySettings->chkMoving->isChecked());
3253 cfg.setCheckersColor1(m_displaySettings->colorChecks1->color().toQColor());
3254 cfg.setCheckersColor2(m_displaySettings->colorChecks2->color().toQColor());
3255 cfg.setCanvasBorderColor(m_displaySettings->canvasBorder->color().toQColor());
3256 cfg.setHideScrollbars(m_displaySettings->hideScrollbars->isChecked());
3257 KoColor c = m_displaySettings->btnSelectionOverlayColor->color();
3258 c.setOpacity(m_displaySettings->sldSelectionOverlayOpacity->value());
3260 cfgImage.setSelectionOutlineOpacity(m_displaySettings->sldSelectionOutlineOpacity->value());
3261 cfg.setAntialiasCurves(m_displaySettings->chkCurveAntialiasing->isChecked());
3262 cfg.setAntialiasSelectionOutline(m_displaySettings->chkSelectionOutlineAntialiasing->isChecked());
3263 cfg.setShowSingleChannelAsColor(m_displaySettings->chkChannelsAsColor->isChecked());
3264 cfg.setHidePopups(m_displaySettings->chkHidePopups->isChecked());
3265
3266 cfg.setHideDockersFullscreen(m_fullscreenSettings->chkDockers->checkState());
3267 cfg.setHideMenuFullscreen(m_fullscreenSettings->chkMenu->checkState());
3268 cfg.setHideScrollbarsFullscreen(m_fullscreenSettings->chkScrollbars->checkState());
3269 cfg.setHideStatusbarFullscreen(m_fullscreenSettings->chkStatusbar->checkState());
3270 cfg.setHideTitlebarFullscreen(m_fullscreenSettings->chkTitlebar->checkState());
3271 cfg.setHideToolbarFullscreen(m_fullscreenSettings->chkToolbar->checkState());
3272
3273 cfg.setCursorMainColor(m_general->cursorColorButton->color().toQColor());
3274 cfg.setEraserCursorMainColor(m_general->eraserCursorColorButton->color().toQColor());
3275 cfg.setPixelGridColor(m_displaySettings->pixelGridColorButton->color().toQColor());
3276 cfg.setPixelGridDrawingThreshold(m_displaySettings->pixelGridDrawingThresholdBox->value() / 100);
3277
3280
3282 cfg.writeEntry("forcedDpiForQtFontBugWorkaround", m_general->forcedFontDpi());
3283 }
3284
3285 return !m_cancelClicked;
3286}
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
float value(const T *src, size_t ch)
qreal u
QList< QString > QStringList
const KoID AlphaColorModelID("A", ki18n("Alpha mask"))
const KoID Float16BitsColorDepthID("F16", ki18n("16-bit float/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
Q_GUI_EXPORT int qt_defaultDpi()
void toggleUseDefaultColorSpace(bool useDefColorSpace)
QList< QLabel * > m_monitorProfileLabels
void toggleAllowMonitorProfileSelection(bool useSystemProfile)
QPointer< KisCIETongueWidget > m_preferredSpaceGraphic
QButtonGroup m_pasteBehaviourGroup
QPointer< QCheckBox > m_chkEnableCanvasColorSpaceManagement
QPointer< KisSqueezedComboBox > m_canvasSurfaceBitDepth
QScopedPointer< KisProofingConfigModel > m_proofModel
QPointer< KisSqueezedComboBox > m_canvasSurfaceColorSpace
QList< KisSqueezedComboBox * > m_monitorProfileWidgets
void refillMonitorProfiles(const KoID &s)
QButtonGroup m_preferredSpaceGraphicMode
ColorSettingsTab(QWidget *parent=0, const char *name=0)
WdgColorSettings * m_page
QScopedPointer< KisScreenMigrationTracker > m_screenMigrationTracker
DisplaySettingsTab(QWidget *parent=0, const char *name=0)
void slotUseOpenGLToggled(bool isChecked)
void slotPreferredSurfaceFormatChanged(int index)
FullscreenSettingsTab(QWidget *parent)
KisConfig::SessionOnStartup sessionOnStartup() const
bool kineticScrollingHiddenScrollbars()
bool saveSessionOnQuit() const
void showAdvancedCumulativeUndoSettings()
int colorSamplerPreviewCircleDiameter() const
bool autoZoomTimelineToPlaybackRange()
static void setButtonGroupEnabled(const QButtonGroup &buttonGroup, bool value)
void colorSamplePreviewThicknessChanged(qreal value)
KisConfig::ColorSamplerPreviewStyle colorSamplerPreviewStyle() const
void colorSamplePreviewOutlineEnabledChanged(int value)
void colorSamplePreviewStyleChanged(int index)
bool colorSamplerPreviewCircleExtraCirclesEnabled() const
bool convertToImageColorspaceOnImport()
QButtonGroup m_pasteFormatGroup
OutlineStyle eraserOutlineStyle()
static KisConfig::ColorSamplerPreviewStyle getColorSamplerPreviewStyleValue(const QComboBox *cmb)
int kineticScrollingSensitivity()
void colorSamplePreviewSizeChanged(int value)
KisCumulativeUndoData m_cumulativeUndoData
void updateTouchPressureSensitivityEnabled(int)
bool showOutlineWhilePainting()
CursorStyle eraserCursorStyle()
static void setColorSamplerPreviewStyleItems(QComboBox *cmb)
static void setColorSamplerPreviewStyleIndexByValue(QComboBox *cmb, KisConfig::ColorSamplerPreviewStyle style)
void enableSubWindowOptions(int)
bool colorSamplerPreviewCircleOutlineEnabled() const
OutlineStyle outlineStyle()
bool showEraserOutlineWhilePainting()
CursorStyle cursorStyle()
qreal colorSamplerPreviewCircleThickness() const
GeneralTab(QWidget *parent=0, const char *name=0)
virtual KisPreferenceSet * createPreferenceSet()=0
static KisActionRegistry * instance()
The KisActionsSnapshot class.
void connectBackwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method)
void connectForwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method)
@ FlipOptionsMode_MenuButton
The flip options are shown as a menu accessible via a options button.
QStringList devices(DeviceType type=screen) const
Return a list of device id's for the specified type.
static KisColorManager * instance()
void setCumulativeUndoData(KisCumulativeUndoData value)
bool backupFile(bool defaultValue=false) const
void setAntialiasCurves(bool v) const
void setSwitchSelectionCtrlAlt(bool value)
bool antialiasSelectionOutline(bool defaultValue=false) const
void setZoomSteps(int steps)
@ ASSISTANTS_DRAW_MODE_PIXMAP_CACHE
Definition kis_config.h:846
@ ASSISTANTS_DRAW_MODE_DIRECT
Definition kis_config.h:845
@ ASSISTANTS_DRAW_MODE_LARGE_PIXMAP_CACHE
Definition kis_config.h:847
int zoomSteps(bool defaultValue=false) const
void setHideDockersFullscreen(const bool value) const
static CanvasSurfaceBitDepthMode canvasSurfaceBitDepthMode(QSettings *settings, bool defaultValue=false)
void setAdaptivePlaybackRange(bool value)
void setEnableCanvasSurfaceColorSpaceManagement(bool value)
bool colorSamplerPreviewCircleOutlineEnabled(bool defaultValue=false) const
void setPasteFormat(qint32 format)
QColor checkersColor2(bool defaultValue=false) const
void setColorSamplerPreviewCircleOutlineEnabled(bool enabled)
void setUseRightMiddleTabletButtonWorkaround(bool value)
void setCheckersColor1(const QColor &v) const
void setHidePopups(bool hidePopups)
void setMDIBackgroundColor(const QString &v) const
QString pressureTabletCurve(bool defaultValue=false) const
void setUndoStackLimit(int limit) const
bool hideScrollbars(bool defaultValue=false) const
int openGLFilteringMode(bool defaultValue=false) const
void setUseZip64(bool value)
bool showSingleChannelAsColor(bool defaultValue=false) const
void setHideToolbarFullscreen(const bool value) const
void setCanvasState(const QString &state) const
int kineticScrollingSensitivity(bool defaultValue=false) const
bool convertToImageColorspaceOnImport(bool defaultValue=false) const
int zoomMarginSize(bool defaultValue=false) const
void setAutoZoomTimelineToPlaybackRange(bool value)
bool showRootLayer(bool defaultValue=false) const
qint32 pasteFormat(bool defaultValue) const
void setEnableBrushSpeedLogging(bool value) const
void setExportMimeType(const QString &defaultExportMimeType)
void setUseWin8PointerInput(bool value)
qreal getPixelGridDrawingThreshold(bool defaultValue=false) const
bool switchSelectionCtrlAlt(bool defaultValue=false) const
void writeEntry(const QString &name, const T &value)
Definition kis_config.h:865
void setRenamePastedLayers(bool value)
QColor checkersColor1(bool defaultValue=false) const
void setHideScrollbars(bool value) const
bool allowLCMSOptimization(bool defaultValue=false) const
static void setCanvasSurfaceBitDepthMode(QSettings *settings, CanvasSurfaceBitDepthMode value)
void setIgnoreHighFunctionKeys(bool value)
bool activateTransformToolAfterPaste(bool defaultValue=false) const
void setNewCursorStyle(CursorStyle style)
bool hideDockersFullscreen(bool defaultValue=false) const
void setEraserCursorStyle(CursorStyle style)
bool compressKra(bool defaultValue=false) const
static bool preferXcbEglProvider(const QSettings *settings, bool defaultValue=false)
bool disableVectorOptimizations(bool defaultValue=false) const
void setCursorMainColor(const QColor &v) const
void setColorSamplerPreviewCircleThickness(qreal thickness)
void setCanvasSurfaceColorSpaceManagementMode(CanvasSurfaceMode value)
void setCumulativeUndoRedo(bool value)
void setConvertToImageColorspaceOnImport(bool value)
void setPixelGridColor(const QColor &v) const
void setToolOptionsInDocker(bool inDocker)
void setForceAlwaysFullSizedOutline(bool value) const
void setLongPressEnabled(bool value)
SessionOnStartup sessionOnStartup(bool defaultValue=false) const
void setForcePaletteColors(bool forcePaletteColors)
void setHideTitlebarFullscreen(const bool value) const
bool enableOpenGLFramerateLogging(bool defaultValue=false) const
QColor getPixelGridColor(bool defaultValue=false) const
bool useDefaultColorSpace(bool defaultvalue=false) const
bool hideMenuFullscreen(bool defaultValue=false) const
QString getMDIBackgroundColor(bool defaultValue=false) const
void setMonitorProfile(int screen, const QString &monitorProfile, bool override) const
void setUseDefaultColorSpace(bool value) const
void setDefaultColorDepth(const QString &depth) const
bool hideScrollbarsFullscreen(bool defaultValue=false) const
TouchPainting touchPainting(bool defaultValue=false) const
void setSeparateEraserCursor(bool value) const
qint32 monitorRenderIntent(bool defaultValue=false) const
void setActivateTransformToolAfterPaste(bool value)
int kineticScrollingGesture(bool defaultValue=false) const
bool useZip64(bool defaultValue=false) const
bool calculateAnimationCacheInBackground(bool defaultValue=false) const
int favoritePresets(bool defaultValue=false) const
bool zoomHorizontal(bool defaultValue=false) const
QString getMDIBackgroundImage(bool defaultValue=false) const
void setAssistantsDrawMode(AssistantsDrawMode value)
CanvasSurfaceMode canvasSurfaceColorSpaceManagementMode(bool defaultValue=false) const
bool hideToolbarFullscreen(bool defaultValue=false) const
bool showCanvasMessages(bool defaultValue=false) const
void setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const
bool useWin8PointerInput(bool defaultValue=false) const
bool useOpenGLTextureBuffer(bool defaultValue=false) const
void setCalculateAnimationCacheInBackground(bool value)
void setColorSamplerPreviewCircleExtraCirclesEnabled(bool enabled)
void setAutoSaveInterval(int seconds) const
void setShowSingleChannelAsColor(bool asColor)
void setTrimFramesImport(bool trim)
bool forcePaletteColors(bool defaultValue=false) const
void setAllowLCMSOptimization(bool allowLCMSOptimization)
void setColorSamplerPreviewCircleDiameter(int style)
void setRenderIntent(qint32 monitorRenderIntent) const
void setFavoritePresets(const int value)
void setEraserOutlineStyle(OutlineStyle style)
void setShowOutlineWhilePainting(bool showOutlineWhilePainting) const
RootSurfaceFormat rootSurfaceFormat(bool defaultValue=false) const
QColor canvasBorderColor(bool defaultValue=false) const
int colorSamplerPreviewCircleDiameter(bool defaultValue=false) const
QString exportMimeType(bool defaultValue) const
void setScrollingCheckers(bool scrollCheckers) const
const QString getScreenStringIdentfier(int screenNo) const
void setBackupFile(bool backupFile) const
void logImportantSettings() const
Log the most interesting settings to the usage log.
Definition kis_config.cc:77
CursorStyle newCursorStyle(bool defaultValue=false) const
bool useCumulativeUndoRedo(bool defaultValue=false) const
void setCheckSize(qint32 checkSize) const
CursorStyle eraserCursorStyle(bool defaultValue=false) const
void setKineticScrollingGesture(int kineticScroll)
void setPreferXcbEglProvider(bool value)
void setPixelGridDrawingThreshold(qreal v) const
void setMonitorForScreen(int screen, const QString &monitor)
void setCanvasBorderColor(const QColor &color) const
QString monitorProfile(int screen) const
get the profile the user has selected for the given screen
@ TOUCH_PAINTING_DISABLED
Definition kis_config.h:50
void setShowCanvasMessages(bool show)
qint32 checkSize(bool defaultValue=false) const
void setWorkingColorSpace(const QString &workingColorSpace) const
KisCumulativeUndoData cumulativeUndoData(bool defaultValue=false) const
OutlineStyle newOutlineStyle(bool defaultValue=false) const
bool forceAlwaysFullSizedOutline(bool defaultValue=false) const
ColorSamplerPreviewStyle
Definition kis_config.h:138
void setPressureTabletCurve(const QString &curveString) const
qreal colorSamplerPreviewCircleThickness(bool defaultValue=false) const
QString workingColorSpace(bool defaultValue=false) const
void setEnableOpenGLFramerateLogging(bool value) const
bool renamePastedLayers(bool defaultValue=false) const
void setNewOutlineStyle(OutlineStyle style)
void setCheckersColor2(const QColor &v) const
void setShowRootLayer(bool showRootLayer) const
OutlineStyle eraserOutlineStyle(bool defaultValue=false) const
void setUseBlackPointCompensation(bool useBlackPointCompensation) const
bool kineticScrollingEnabled(bool defaultValue=false) const
void setUseOpenGLTextureBuffer(bool useBuffer)
void setTrimKra(bool trim)
bool hideTitlebarFullscreen(bool defaultValue=false) const
bool useRightMiddleTabletButtonWorkaround(bool defaultValue=false) const
bool longPressEnabled(bool defaultValue=false) const
void setColorSamplerPreviewStyle(ColorSamplerPreviewStyle style)
bool hidePopups(bool defaultValue=false) const
bool enableCanvasSurfaceColorSpaceManagement(bool defaultValue=false) const
void setRootSurfaceFormat(RootSurfaceFormat value)
bool autoPinLayersToTimeline(bool defaultValue=false) const
bool toolOptionsInDocker(bool defaultValue=false) const
void setOpenGLFilteringMode(int filteringMode)
void setKineticScrollingHideScrollbars(bool scrollbar)
void setAntialiasSelectionOutline(bool v) const
bool trimKra(bool defaultValue=false) const
bool enableBrushSpeedLogging(bool defaultValue=false) const
bool forceAlwaysFullSizedEraserOutline(bool defaultValue=false) const
T readEntry(const QString &name, const T &defaultValue=T())
Definition kis_config.h:875
int autoSaveInterval(bool defaultValue=false) const
QString defColorModel(bool defaultValue=false) const
void setDisableVectorOptimizations(bool value)
void setHideStatusbarFullscreen(const bool value) const
void setCompressKra(bool compress)
void setTouchPainting(TouchPainting value) const
bool showOutlineWhilePainting(bool defaultValue=false) const
void setShowEraserOutlineWhilePainting(bool showEraserOutlineWhilePainting) const
void setHideMenuFullscreen(const bool value) const
bool useSystemMonitorProfile(bool defaultValue=false) const
bool autoZoomTimelineToPlaybackRange(bool defaultValue=false) const
bool scrollCheckers(bool defaultValue=false) const
CanvasSurfaceBitDepthMode
Definition kis_config.h:189
void setZoomMarginSize(int zoomMarginSize)
bool hideStatusbarFullscreen(bool defaultValue=false) const
bool colorSamplerPreviewCircleExtraCirclesEnabled(bool defaultValue=false) const
void setZoomHorizontal(bool value)
bool kineticScrollingHiddenScrollbars(bool defaultValue=false) const
bool useOpenGL(bool defaultValue=false) const
bool trimFramesImport(bool defaultValue=false) const
void setForceAlwaysFullSizedEraserOutline(bool value) const
bool selectionActionBar(bool defaultValue=false) const
int undoStackLimit(bool defaultValue=false) const
bool useBlackPointCompensation(bool defaultValue=false) const
bool saveSessionOnQuit(bool defaultValue) const
ColorSamplerPreviewStyle colorSamplerPreviewStyle(bool defaultValue=false) const
void setMDIBackgroundImage(const QString &fileName) const
QColor getCursorMainColor(bool defaultValue=false) const
void setSelectionActionBar(bool value)
qint32 pasteBehaviour(bool defaultValue=false) const
AssistantsDrawMode assistantsDrawMode(bool defaultValue=false) const
bool separateEraserCursor(bool defaultValue=false) const
void setEraserCursorMainColor(const QColor &v) const
void setSaveSessionOnQuit(bool value)
bool disableAVXOptimizations(bool defaultValue=false) const
bool showEraserOutlineWhilePainting(bool defaultValue=false) const
void setPasteBehaviour(qint32 behaviour) const
void setSessionOnStartup(SessionOnStartup value)
void setHideScrollbarsFullscreen(const bool value) const
QString monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue=true) const
void setAutoPinLayersToTimeline(bool value)
QColor getEraserCursorMainColor(bool defaultValue=false) const
bool antialiasCurves(bool defaultValue=false) const
void setKineticScrollingSensitivity(int sensitivity)
bool ignoreHighFunctionKeys(bool defaultValue=false) const
void setDisableAVXOptimizations(bool value)
bool adaptivePlaybackRange(bool defaultValue=false) const
void setKineticScrollingEnabled(bool enabled)
std::pair< KoColorConversionTransformation::Intent, KoColorConversionTransformation::ConversionFlags > Options
KisCumulativeUndoData cumulativeUndoData() const
KoConfigAuthorPage * m_authorPage
PerformanceTab * m_performanceSettings
ColorSettingsTab * m_colorSettings
PopupPaletteTab * m_popupPaletteSettings
KPageWidgetItem * getPage(Page page_enum)
KisInputConfigurationPage * m_inputConfiguration
FullscreenSettingsTab * m_fullscreenSettings
ShortcutSettingsTab * m_shortcutSettings
TabletSettingsTab * m_tabletSettings
bool editPreferences(std::optional< PageDesc > page)
QList< KPageWidgetItem * > m_pages
DisplaySettingsTab * m_displaySettings
void slotButtonClicked(QAbstractButton *button)
KisDlgPreferences(QWidget *parent=0, const char *name=0)
void switchTab(PageDesc tab)
void showEvent(QShowEvent *event) override
void setEnableProgressReporting(bool value)
void setUseAnimationCacheRegionOfInterest(bool value)
bool useAnimationCacheFrameSizeLimit(bool defaultValue=false) const
void setAnimationCacheFrameSizeLimit(int value)
void setFrameRenderingClones(int value)
int animationCacheFrameSizeLimit(bool defaultValue=false) const
KisProofingConfigurationSP defaultProofingconfiguration(bool requestDefault=false)
void setMaxNumberOfThreads(int value)
bool useAnimationCacheRegionOfInterest(bool defaultValue=false) const
int frameRenderingClones(bool defaultValue=false) const
void setDetectFpsLimit(bool value)
void setFpsLimit(int value)
QString swapDir(bool requestDefault=false)
int maxNumberOfThreads(bool defaultValue=false) const
qreal memoryPoolLimitPercent(bool requestDefault=false) const
void setEnablePerfLog(bool value)
bool detectFpsLimit(bool defaultValue=false) const
bool enableProgressReporting(bool requestDefault=false) const
void setUseAnimationCacheFrameSizeLimit(bool value)
int fpsLimit(bool defaultValue=false) const
void setSelectionOutlineOpacity(qreal value)
int maxSwapSize(bool requestDefault=false) const
void setUseOnDiskAnimationCacheSwapping(bool value)
qreal animationCacheRegionOfInterestMargin(bool defaultValue=false) const
void setFrameRenderingTimeout(int value)
void setMaxSwapSize(int value)
qreal memoryHardLimitPercent(bool requestDefault=false) const
void setMemorySoftLimitPercent(qreal value)
void setSwapDir(const QString &swapDir)
void setSelectionOverlayMaskColor(const QColor &color)
qreal selectionOutlineOpacity(bool defaultValue=false) const
void setRenameDuplicatedLayers(bool value)
static int totalRAM()
int frameRenderingTimeout(bool defaultValue=false) const
bool enablePerfLog(bool requestDefault=false) const
void setMaxBrushSize(int value)
void setRenameMergedLayers(bool value)
void setDefaultProofingConfig(const KisProofingConfiguration &config)
QColor selectionOverlayMaskColor(bool defaultValue=false) const
qreal memorySoftLimitPercent(bool requestDefault=false) const
void setMemoryHardLimitPercent(qreal value)
bool useOnDiskAnimationCacheSwapping(bool defaultValue=false) const
void setMemoryPoolLimitPercent(qreal value)
void setAnimationCacheRegionOfInterestMargin(qreal value)
static QStringList supportedMimeTypes(Direction direction)
A Configuration Dialog Page to configure the canvas input.
A container for a set of QAction objects.
Q_INVOKABLE QAction * addAction(const QString &name, QAction *action)
QList< QAction * > actions() const
virtual KisKActionCollection * actionCollection() const
Main window for Krita.
static QString descriptionForMimeType(const QString &mimeType)
Find the user-readable description for the given mimetype.
static KisOpenGLModeProber * instance()
QSurfaceFormat surfaceformatInUse() const
static OpenGLRenderer getCurrentOpenGLRenderer()
static OpenGLRenderers getSupportedOpenGLRenderers()
@ RendererSoftware
Definition kis_opengl.h:45
@ RendererDesktopGL
Definition kis_opengl.h:43
@ RendererOpenGLES
Definition kis_opengl.h:44
static QStringList getOpenGLWarnings()
static bool supportsLoD()
static OpenGLRenderer getUserPreferredOpenGLRendererConfig()
static OpenGLRenderer getQtPreferredOpenGLRenderer()
XcbGLProviderProtocol
Definition kis_opengl.h:63
static std::optional< XcbGLProviderProtocol > xcbGlProviderProtocol()
static void setUserPreferredOpenGLRendererConfig(OpenGLRenderer renderer)
static KisPart * instance()
Definition KisPart.cpp:131
KisMainWindow * currentMainwindow() const
Definition KisPart.cpp:459
static KisPlatformPluginInterfaceFactory * instance()
static KisPreferenceSetRegistry * instance()
virtual QIcon icon()=0
virtual QString header()=0
virtual void loadPreferences()=0
virtual QString name()=0
The KisProofingConfigModel class.
static const QString resourceLocationKey
std::optional< KisSurfaceColorimetry::SurfaceDescription > currentSurfaceDescription() const
ScreenInfo infoForScreen(QScreen *screen) const
void sigScreenChanged(QScreen *screen)
void addCollection(KisKActionCollection *, const QString &title=QString())
static KisSurfaceColorSpaceWrapper fromQtColorSpace(const QColorSpace &colorSpace)
static KoColorSpaceEngineRegistry * instance()
static KoColor fromXML(const QDomElement &elt, const QString &channelDepthId)
Definition KoColor.cpp:350
void setColor(const quint8 *data, const KoColorSpace *colorSpace=0)
Definition KoColor.cpp:186
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
Definition KoColor.cpp:213
void toQColor(QColor *c) const
a convenience method for the above.
Definition KoColor.cpp:198
static const Colorimetry DCIP3
static const Colorimetry BT2020
static const Colorimetry BT709
static const Colorimetry DisplayP3
static const Colorimetry AdobeRGB
const T value(const QString &id) const
T get(const QString &id) const
QList< QString > keys() const
Definition KoID.h:30
QString id() const
Definition KoID.cpp:63
static bool tabletInputReceived()
static void getAllUserResourceFoldersLocationsForWindowsStore(QString &standardLocation, QString &privateLocation)
getAllAppDataLocationsForWindowsStore Use this to get both private and general appdata folders which ...
static QString getAppDataLocation()
static QString saveLocation(const QString &type, const QString &suffix=QString(), bool create=true)
void load(bool requestDefault)
PerformanceTab(QWidget *parent=0, const char *name=0)
QScopedPointer< KisFrameRateLimitModel > m_frameRateModel
void slotThreadsLimitChanged(int value)
QVector< SliderAndSpinBoxSync * > m_syncs
void slotFrameClonesLimitChanged(int value)
PopupPaletteTab(QWidget *parent=0, const char *name=0)
void slotSelectorTypeChanged(int index)
WdgShortcutSettings * m_page
QScopedPointer< KisActionsSnapshot > m_snapshot
ShortcutSettingsTab(QWidget *parent=0, const char *name=0)
WdgTabletSettings * m_page
TabletSettingsTab(QWidget *parent=0, const char *name=0)
bool eventFilter(QObject *, QEvent *event) override
UnscrollableComboBox(QObject *parent)
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
int getTotalRAM()
QString shortNameOfDisplay(int index)
Q_GUI_EXPORT int qt_defaultDpi()
QIcon addDisabledStatesToIcon(const QIcon &_icon, const QSize &size)
OutlineStyle
Definition kis_global.h:53
CursorStyle
Definition kis_global.h:62
#define koIcon(name)
Use these macros for icons without any issues.
Definition kis_icon.h:25
QString button(const QWheelEvent &ev)
QIcon loadIcon(const QString &name)
void setText(QSpinBox *spinBox, const QStringView textTemplate)
void install(QSpinBox *spinBox, std::function< QString(int)> messageFn)
void connectControl(KisCompositeOpListWidget *widget, QObject *source, const char *property)
void connectControlState(QSpinBox *spinBox, QObject *source, const char *readStateProperty, const char *writeProperty)
static const QStringList allowedColorHistorySortingValues({"none", "hsv"})
State validate(QString &line, int &) const override
BackupSuffixValidator(QObject *parent)
const QStringList invalidCharacters
void linkActivated(const QString &link)
virtual bool isSuitableForDisplay() const =0
virtual const KoColorProfile * addProfile(const QString &filename)=0
QString colorSpaceId(const QString &colorModelId, const QString &colorDepthId) const
static KoColorSpaceRegistry * instance()
KoID colorSpaceColorDepthId(const QString &_colorSpaceId) const
QString defaultProfileForColorSpace(const QString &colorSpaceId) const
KoID colorSpaceColorModelId(const QString &_colorSpaceId) const
QList< KoID > listKeys() const
State validate(QString &line, int &) const override
WritableLocationValidator(QObject *parent)