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