File indexing completed on 2024-05-26 04:30:06

0001 /*
0002  *  preferencesdlg.cc - part of KImageShop
0003  *
0004  *  SPDX-FileCopyrightText: 1999 Michael Koch <koch@kde.org>
0005  *  SPDX-FileCopyrightText: 2003-2011 Boudewijn Rempt <boud@valdyas.org>
0006  *
0007  *  SPDX-License-Identifier: GPL-2.0-or-later
0008  */
0009 
0010 #include "kis_dlg_preferences.h"
0011 
0012 #include <config-hdr.h>
0013 #include <opengl/kis_opengl.h>
0014 
0015 #include <QBitmap>
0016 #include <QCheckBox>
0017 #include <QComboBox>
0018 #include <QClipboard>
0019 #include <QCursor>
0020 #include <QDesktopWidget>
0021 #include <QFileDialog>
0022 #include <QFormLayout>
0023 #include <QGridLayout>
0024 #include <QGroupBox>
0025 #include <QLabel>
0026 #include <QLayout>
0027 #include <QLineEdit>
0028 #include <QMdiArea>
0029 #include <QMessageBox>
0030 #include <QPushButton>
0031 #include <QRadioButton>
0032 #include <QSettings>
0033 #include <QSlider>
0034 #include <QStandardPaths>
0035 #include <QThread>
0036 #include <QToolButton>
0037 #include <QStyleFactory>
0038 #include <QScreen>
0039 #include <QFontComboBox>
0040 #include <QFont>
0041 
0042 #include <KisApplication.h>
0043 #include <KisDocument.h>
0044 #include <kis_icon.h>
0045 #include <KisPart.h>
0046 #include <KisSpinBoxI18nHelper.h>
0047 #include <KoColorModelStandardIds.h>
0048 #include <KoColorProfile.h>
0049 #include <KoColorSpaceEngine.h>
0050 #include <KoConfigAuthorPage.h>
0051 #include <KoConfig.h>
0052 #include <KoFileDialog.h>
0053 #include "KoID.h"
0054 #include <KoVBox.h>
0055 
0056 #include <KTitleWidget>
0057 #include <KoResourcePaths.h>
0058 #include <kformat.h>
0059 #include <klocalizedstring.h>
0060 #include <kstandardguiitem.h>
0061 #include <kundo2stack.h>
0062 
0063 #include <KisResourceCacheDb.h>
0064 #include <KisResourceLocator.h>
0065 
0066 #include "KisProofingConfiguration.h"
0067 #include "KoColorConversionTransformation.h"
0068 #include "kis_action_registry.h"
0069 #include <kis_image.h>
0070 #include <KisSqueezedComboBox.h>
0071 #include "kis_clipboard.h"
0072 #include "widgets/kis_cmb_idlist.h"
0073 #include "KoColorSpace.h"
0074 #include "KoColorSpaceRegistry.h"
0075 #include "kis_canvas_resource_provider.h"
0076 #include "kis_color_manager.h"
0077 #include "kis_config.h"
0078 #include "kis_cursor.h"
0079 #include "kis_image_config.h"
0080 #include "kis_preference_set_registry.h"
0081 #include "KisMainWindow.h"
0082 
0083 #include "kis_file_name_requester.h"
0084 
0085 #include "slider_and_spin_box_sync.h"
0086 
0087 // for the performance update
0088 #include <kis_cubic_curve.h>
0089 #include <kis_signals_blocker.h>
0090 
0091 #include "input/config/kis_input_configuration_page.h"
0092 #include "input/wintab/drawpile_tablettester/tablettester.h"
0093 
0094 #include "KisDlgConfigureCumulativeUndo.h"
0095 
0096 #ifdef Q_OS_WIN
0097 #include "config_use_qt_tablet_windows.h"
0098 #   ifndef USE_QT_TABLET_WINDOWS
0099 #       include <kis_tablet_support_win8.h>
0100 #   endif
0101 #include "config-high-dpi-scale-factor-rounding-policy.h"
0102 #include "KisWindowsPackageUtils.h"
0103 #endif
0104 
0105 /**
0106  * HACK ALERT: this is a function from a private Qt's header qfont_p.h,
0107  * we don't include the whole header, because it is painful in the
0108  * environments we don't fully control, e.g. in distribution packages.
0109  */
0110 Q_GUI_EXPORT int qt_defaultDpi();
0111 
0112 QString shortNameOfDisplay(int index)
0113 {
0114     if (QGuiApplication::screens().length() <= index) {
0115         return QString();
0116     }
0117     QScreen* screen = QGuiApplication::screens()[index];
0118     QString resolution = QString::number(screen->geometry().width()).append("x").append(QString::number(screen->geometry().height()));
0119     QString name = screen->name();
0120     // 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
0121 
0122     KisConfig cfg(true);
0123     QString shortName = resolution + " " + name + " " + cfg.getScreenStringIdentfier(index);
0124     return shortName;
0125 }
0126 
0127 
0128 struct WritableLocationValidator : public QValidator {
0129     WritableLocationValidator(QObject *parent)
0130         : QValidator(parent)
0131     {
0132     }
0133 
0134     State validate(QString &line, int &/*pos*/) const override
0135     {
0136         QFileInfo fi(line);
0137         if (!fi.isWritable()) {
0138             return Invalid;
0139         }
0140         return Acceptable;
0141     }
0142 };
0143 
0144 struct BackupSuffixValidator : public QValidator {
0145     BackupSuffixValidator(QObject *parent)
0146         : QValidator(parent)
0147         , invalidCharacters(QStringList()
0148                             << "0" << "1" << "2" << "3" << "4" << "5" << "6" << "7" << "8" << "9"
0149                             << "/" << "\\" << ":" << ";" << " ")
0150     {}
0151 
0152     ~BackupSuffixValidator() override {}
0153 
0154     const QStringList invalidCharacters;
0155 
0156     State validate(QString &line, int &/*pos*/) const override
0157     {
0158         Q_FOREACH(const QString invalidChar, invalidCharacters) {
0159             if (line.contains(invalidChar)) {
0160                 return Invalid;
0161             }
0162         }
0163         return Acceptable;
0164     }
0165 };
0166 
0167 /*
0168  * We need this because the final item in the ComboBox is a used as an action to launch file selection dialog.
0169  * So disabling it makes sure that user doesn't accidentally scroll and select it and get confused why the
0170  * file picker launched.
0171  */
0172 class UnscrollableComboBox : public QObject
0173 {
0174 public:
0175     UnscrollableComboBox(QObject *parent)
0176         : QObject(parent)
0177     {
0178     }
0179 
0180     bool eventFilter(QObject *, QEvent *event) override
0181     {
0182         if (event->type() == QEvent::Wheel) {
0183             event->accept();
0184             return true;
0185         }
0186         return false;
0187     }
0188 };
0189 
0190 GeneralTab::GeneralTab(QWidget *_parent, const char *_name)
0191     : WdgGeneralSettings(_parent, _name)
0192 {
0193     KisConfig cfg(true);
0194 
0195     // HACK ALERT!
0196     // QScrollArea contents are opaque at multiple levels
0197     // The contents themselves AND the viewport widget
0198     {
0199         scrollAreaWidgetContents->setAutoFillBackground(false);
0200         scrollAreaWidgetContents->parentWidget()->setAutoFillBackground(false);
0201     }
0202 
0203     //
0204     // Cursor Tab
0205     //
0206 
0207     QStringList cursorItems = QStringList()
0208             << i18n("No Cursor")
0209             << i18n("Tool Icon")
0210             << i18n("Arrow")
0211             << i18n("Small Circle")
0212             << i18n("Crosshair")
0213             << i18n("Triangle Righthanded")
0214             << i18n("Triangle Lefthanded")
0215             << i18n("Black Pixel")
0216             << i18n("White Pixel");
0217 
0218     QStringList outlineItems = QStringList()
0219             << i18nc("Display options label to not DISPLAY brush outline", "No Outline")
0220             << i18n("Circle Outline")
0221             << i18n("Preview Outline")
0222             << i18n("Tilt Outline");
0223 
0224     // brush
0225 
0226     m_cmbCursorShape->addItems(cursorItems);
0227 
0228     m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle());
0229 
0230     m_cmbOutlineShape->addItems(outlineItems);
0231 
0232     m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle());
0233 
0234     m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting());
0235     m_changeBrushOutline->setChecked(!cfg.forceAlwaysFullSizedOutline());
0236 
0237     KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8());
0238     cursorColor.fromQColor(cfg.getCursorMainColor());
0239     cursorColorButton->setColor(cursorColor);
0240 
0241     // eraser
0242 
0243     m_chkSeparateEraserCursor->setChecked(cfg.separateEraserCursor());
0244 
0245     m_cmbEraserCursorShape->addItems(cursorItems);
0246     m_cmbEraserCursorShape->addItem(i18n("Eraser"));
0247 
0248     m_cmbEraserCursorShape->setCurrentIndex(cfg.eraserCursorStyle());
0249 
0250     m_cmbEraserOutlineShape->addItems(outlineItems);
0251 
0252     m_cmbEraserOutlineShape->setCurrentIndex(cfg.eraserOutlineStyle());
0253 
0254     m_showEraserOutlinePainting->setChecked(cfg.showEraserOutlineWhilePainting());
0255     m_changeEraserBrushOutline->setChecked(!cfg.forceAlwaysFullSizedEraserOutline());
0256 
0257     KoColor eraserCursorColor(KoColorSpaceRegistry::instance()->rgb8());
0258     eraserCursorColor.fromQColor(cfg.getEraserCursorMainColor());
0259     eraserCursorColorButton->setColor(eraserCursorColor);
0260 
0261     //
0262     // Window Tab
0263     //
0264     chkUseCustomFont->setChecked(cfg.readEntry<bool>("use_custom_system_font", false));
0265     cmbCustomFont->findChild <QComboBox*>("stylesComboBox")->setVisible(false);
0266 
0267     QString fontName = cfg.readEntry<QString>("custom_system_font", "");
0268     if (fontName.isEmpty()) {
0269         cmbCustomFont->setCurrentFont(qApp->font());
0270 
0271     }
0272     else {
0273         int pointSize = qApp->font().pointSize();
0274         cmbCustomFont->setCurrentFont(QFont(fontName, pointSize));
0275     }
0276     int fontSize = cfg.readEntry<int>("custom_font_size", -1);
0277     if (fontSize < 0) {
0278         intFontSize->setValue(qApp->font().pointSize());
0279     }
0280     else {
0281         intFontSize->setValue(fontSize);
0282     }
0283 
0284     m_cmbMDIType->setCurrentIndex(cfg.readEntry<int>("mdi_viewmode", (int)QMdiArea::TabbedView));
0285     enableSubWindowOptions(m_cmbMDIType->currentIndex());
0286     connect(m_cmbMDIType, SIGNAL(currentIndexChanged(int)), SLOT(enableSubWindowOptions(int)));
0287 
0288     m_backgroundimage->setText(cfg.getMDIBackgroundImage());
0289     connect(m_bnFileName, SIGNAL(clicked()), SLOT(getBackgroundImage()));
0290     connect(clearBgImageButton, SIGNAL(clicked()), SLOT(clearBackgroundImage()));
0291 
0292     QString xml = cfg.getMDIBackgroundColor();
0293     KoColor mdiColor = KoColor::fromXML(xml);
0294     m_mdiColor->setColor(mdiColor);
0295 
0296     m_chkRubberBand->setChecked(cfg.readEntry<int>("mdi_rubberband", cfg.useOpenGL()));
0297 
0298     m_chkCanvasMessages->setChecked(cfg.showCanvasMessages());
0299 
0300     const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
0301     QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
0302     m_chkHiDPI->setChecked(kritarc.value("EnableHiDPI", true).toBool());
0303 #ifdef HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY
0304     m_chkHiDPIFractionalScaling->setChecked(kritarc.value("EnableHiDPIFractionalScaling", false).toBool());
0305 #else
0306     m_wdgHiDPIFractionalScaling->setEnabled(false);
0307 #endif
0308     chkUsageLogging->setChecked(kritarc.value("LogUsage", true).toBool());
0309 
0310 
0311     //
0312     // Tools tab
0313     //
0314     m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker());
0315     cmbFlowMode->setCurrentIndex((int)!cfg.readEntry<bool>("useCreamyAlphaDarken", true));
0316     cmbCmykBlendingMode->setCurrentIndex((int)!cfg.readEntry<bool>("useSubtractiveBlendingForCmykColorSpaces", true));
0317     m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt());
0318     chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas());
0319     chkEnableTransformToolAfterPaste->setChecked(cfg.activateTransformToolAfterPaste());
0320     chkZoomHorizontally->setChecked(cfg.zoomHorizontal());
0321 
0322     m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled());
0323 
0324     m_cmbKineticScrollingGesture->addItem(i18n("On Touch Drag"));
0325     m_cmbKineticScrollingGesture->addItem(i18n("On Click Drag"));
0326     m_cmbKineticScrollingGesture->addItem(i18n("On Middle-Click Drag"));
0327     //m_cmbKineticScrollingGesture->addItem(i18n("On Right Click Drag"));
0328 
0329     spnZoomSteps->setValue(cfg.zoomSteps());
0330 
0331 
0332     m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture());
0333     m_kineticScrollingSensitivitySlider->setRange(0, 100);
0334     m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity());
0335     m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars());
0336 
0337     intZoomMarginSize->setValue(cfg.zoomMarginSize());
0338 
0339     //
0340     // File handling
0341     //
0342     int autosaveInterval = cfg.autoSaveInterval();
0343     //convert to minutes
0344     m_autosaveSpinBox->setValue(autosaveInterval / 60);
0345     m_autosaveCheckBox->setChecked(autosaveInterval > 0);
0346     chkHideAutosaveFiles->setChecked(cfg.readEntry<bool>("autosavefileshidden", true));
0347 
0348     m_chkCompressKra->setChecked(cfg.compressKra());
0349     chkZip64->setChecked(cfg.useZip64());
0350     m_chkTrimKra->setChecked(cfg.trimKra());
0351     m_chkTrimFramesImport->setChecked(cfg.trimFramesImport());
0352 
0353     m_backupFileCheckBox->setChecked(cfg.backupFile());
0354     cmbBackupFileLocation->setCurrentIndex(cfg.readEntry<int>("backupfilelocation", 0));
0355     txtBackupFileSuffix->setText(cfg.readEntry<QString>("backupfilesuffix", "~"));
0356     QValidator *validator = new BackupSuffixValidator(txtBackupFileSuffix);
0357     txtBackupFileSuffix->setValidator(validator);
0358     intNumBackupFiles->setValue(cfg.readEntry<int>("numberofbackupfiles", 1));
0359 
0360     //
0361     // Miscellaneous
0362     //
0363     cmbStartupSession->addItem(i18n("Open default window"));
0364     cmbStartupSession->addItem(i18n("Load previous session"));
0365     cmbStartupSession->addItem(i18n("Show session manager"));
0366     cmbStartupSession->setCurrentIndex(cfg.sessionOnStartup());
0367 
0368     chkSaveSessionOnQuit->setChecked(cfg.saveSessionOnQuit(false));
0369 
0370     m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport());
0371 
0372     m_undoStackSize->setValue(cfg.undoStackLimit());
0373     chkCumulativeUndo->setChecked(cfg.useCumulativeUndoRedo());
0374     connect(chkCumulativeUndo, SIGNAL(toggled(bool)), btnAdvancedCumulativeUndo, SLOT(setEnabled(bool)));
0375     btnAdvancedCumulativeUndo->setEnabled(chkCumulativeUndo->isChecked());
0376     connect(btnAdvancedCumulativeUndo, SIGNAL(clicked()), SLOT(showAdvancedCumulativeUndoSettings()));
0377     m_cumulativeUndoData = cfg.cumulativeUndoData();
0378 
0379     chkShowRootLayer->setChecked(cfg.showRootLayer());
0380 
0381     m_chkAutoPin->setChecked(cfg.autoPinLayersToTimeline());
0382     m_chkAdaptivePlaybackRange->setChecked(cfg.adaptivePlaybackRange());
0383 
0384     chkRenameMergedLayers->setChecked(KisImageConfig(true).renameMergedLayers());
0385     chkRenamePastedLayers->setChecked(cfg.renamePastedLayers());
0386 
0387     KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs");
0388     bool dontUseNative = true;
0389 #ifdef Q_OS_ANDROID
0390     dontUseNative = false;
0391 #endif
0392 #ifdef Q_OS_UNIX
0393     if (qgetenv("XDG_CURRENT_DESKTOP") == "KDE") {
0394         dontUseNative = false;
0395     }
0396 #endif
0397 #ifdef Q_OS_MACOS
0398     dontUseNative = false;
0399 #endif
0400 #ifdef Q_OS_WIN
0401     dontUseNative = false;
0402 #endif
0403     m_chkNativeFileDialog->setChecked(!group.readEntry("DontUseNativeFileDialog", dontUseNative));
0404 
0405     if (!qEnvironmentVariable("APPIMAGE").isEmpty()) {
0406         // AppImages don't have access to platform plugins. BUG: 447805
0407         // Setting the checkbox to false is 
0408         m_chkNativeFileDialog->setChecked(false);
0409         m_chkNativeFileDialog->setEnabled(false);
0410     }
0411 
0412     intMaxBrushSize->setValue(KisImageConfig(true).maxBrushSize());
0413 
0414     //
0415     // Resources
0416     //
0417     m_urlResourceFolder->setMode(KoFileDialog::OpenDirectory);
0418     m_urlResourceFolder->setConfigurationName("resource_directory");
0419     const QString resourceLocation = KoResourcePaths::getAppDataLocation();
0420     if (QFileInfo(resourceLocation).isWritable()) {
0421         m_urlResourceFolder->setFileName(resourceLocation);
0422     }
0423     else {
0424         m_urlResourceFolder->setFileName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
0425     }
0426     QValidator *writableValidator = new WritableLocationValidator(m_urlResourceFolder);
0427     txtBackupFileSuffix->setValidator(writableValidator);
0428     connect(m_urlResourceFolder, SIGNAL(textChanged(QString)), SLOT(checkResourcePath()));
0429     checkResourcePath();
0430 
0431     grpRestartMessage->setPixmap(
0432         grpRestartMessage->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
0433     grpRestartMessage->setText(i18n("You will need to Restart Krita for the changes to take an effect."));
0434 
0435     grpAndroidWarningMessage->setVisible(false);
0436     grpAndroidWarningMessage->setPixmap(
0437         grpAndroidWarningMessage->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
0438     grpAndroidWarningMessage->setText(
0439         i18n("Saving at a Location picked from the File Picker may slow down the startup!"));
0440 
0441 #ifdef Q_OS_ANDROID
0442     m_urlResourceFolder->setVisible(false);
0443 
0444     m_resourceFolderSelector->setVisible(true);
0445     m_resourceFolderSelector->installEventFilter(new UnscrollableComboBox(this));
0446 
0447     const QList<QPair<QString, QString>> writableLocations = []() {
0448         QList<QPair<QString, QString>> writableLocationsAndText;
0449         // filters out the duplicates
0450         const QList<QString> locations = []() {
0451             QStringList filteredLocations;
0452             const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
0453             Q_FOREACH(const QString &location, locations) {
0454                 if (!filteredLocations.contains(location)) {
0455                     filteredLocations.append(location);
0456                 }
0457             }
0458             return filteredLocations;
0459         }();
0460 
0461         bool isFirst = true;
0462 
0463         Q_FOREACH (QString location, locations) {
0464             QString text;
0465             QFileInfo fileLocation(location);
0466             // The first one that we get from is the "Default"
0467             if (isFirst) {
0468                 text = i18n("Default");
0469                 isFirst = false;
0470             } else if (location.startsWith("/data")) {
0471                 text = i18n("Internal Storage");
0472             } else {
0473                 text = i18n("SD-Card");
0474             }
0475             if (fileLocation.isWritable()) {
0476                 writableLocationsAndText.append({text, location});
0477             }
0478         }
0479         return writableLocationsAndText;
0480     }();
0481 
0482     for (auto it = writableLocations.constBegin(); it != writableLocations.constEnd(); ++it) {
0483         m_resourceFolderSelector->addItem(it->first + " - " + it->second);
0484         // we need it to extract out the path
0485         m_resourceFolderSelector->setItemData(m_resourceFolderSelector->count() - 1, it->second, Qt::UserRole);
0486     }
0487 
0488     // if the user has selected a custom location, we add it to the list as well.
0489     if (resourceLocation.startsWith("content://")) {
0490         m_resourceFolderSelector->addItem(resourceLocation);
0491         int index = m_resourceFolderSelector->count() - 1;
0492         m_resourceFolderSelector->setItemData(index, resourceLocation, Qt::UserRole);
0493         m_resourceFolderSelector->setCurrentIndex(index);
0494         grpAndroidWarningMessage->setVisible(true);
0495     } else {
0496         // find the index of the current resource location in the writableLocation, so we can set our view to that
0497         auto iterator = std::find_if(writableLocations.constBegin(),
0498                                      writableLocations.constEnd(),
0499                                      [&resourceLocation](QPair<QString, QString> location) {
0500                                          return location.second == resourceLocation;
0501                                      });
0502 
0503         if (iterator != writableLocations.constEnd()) {
0504             int index = writableLocations.indexOf(*iterator);
0505             KIS_SAFE_ASSERT_RECOVER_NOOP(index < m_resourceFolderSelector->count());
0506             m_resourceFolderSelector->setCurrentIndex(index);
0507         }
0508     }
0509 
0510     // this should be the last item we add.
0511     m_resourceFolderSelector->addItem(i18n("Choose Manually"));
0512 
0513     connect(m_resourceFolderSelector, qOverload<int>(&QComboBox::activated), [this](int index) {
0514         const int previousIndex = m_resourceFolderSelector->currentIndex();
0515 
0516         // if it is the last item in the last item, then open file picker and set the name returned as the filename
0517         if (m_resourceFolderSelector->count() - 1 == index) {
0518             KoFileDialog dialog(this, KoFileDialog::OpenDirectory, "Select Directory");
0519             const QString selectedDirectory = dialog.filename();
0520 
0521             if (!selectedDirectory.isEmpty()) {
0522                 // if the index above "Choose Manually" is a content Uri, then we just modify it, and then set that as
0523                 // the index.
0524                 if (m_resourceFolderSelector->itemData(index - 1, Qt::DisplayRole)
0525                         .value<QString>()
0526                         .startsWith("content://")) {
0527                     m_resourceFolderSelector->setItemText(index - 1, selectedDirectory);
0528                     m_resourceFolderSelector->setItemData(index - 1, selectedDirectory, Qt::UserRole);
0529                     m_resourceFolderSelector->setCurrentIndex(index - 1);
0530                 } else {
0531                     // There isn't any content Uri in the ComboBox list, so just insert one, and set that as the index.
0532                     m_resourceFolderSelector->insertItem(index, selectedDirectory);
0533                     m_resourceFolderSelector->setItemData(index, selectedDirectory, Qt::UserRole);
0534                     m_resourceFolderSelector->setCurrentIndex(index);
0535                 }
0536                 // since we have selected the custom location, make the warning visible.
0537                 grpAndroidWarningMessage->setVisible(true);
0538             } else {
0539                 m_resourceFolderSelector->setCurrentIndex(previousIndex);
0540             }
0541         }
0542 
0543         // hide-unhide based on the selection of user.
0544         grpAndroidWarningMessage->setVisible(
0545             m_resourceFolderSelector->currentData(Qt::UserRole).value<QString>().startsWith("content://"));
0546     });
0547 
0548 #else
0549     m_resourceFolderSelector->setVisible(false);
0550 #endif
0551 
0552     grpWindowsAppData->setVisible(false);
0553 #ifdef Q_OS_WIN
0554     QString folderInStandardAppData;
0555     QString folderInPrivateAppData;
0556     KoResourcePaths::getAllUserResourceFoldersLocationsForWindowsStore(folderInStandardAppData, folderInPrivateAppData);
0557 
0558     if (!folderInPrivateAppData.isEmpty()) {
0559         const auto pathToDisplay = [](const QString &path) {
0560             // Due to how Unicode word wrapping works, the string does not
0561             // wrap after backslashes in Qt 5.12. We don't want the path to
0562             // become too long, so we add a U+200B ZERO WIDTH SPACE to allow
0563             // wrapping. The downside is that we cannot let the user select
0564             // and copy the path because it now contains invisible unicode
0565             // code points.
0566             // See: https://bugreports.qt.io/browse/QTBUG-80892
0567             return QDir::toNativeSeparators(path).replace(QChar('\\'), QStringLiteral(u"\\\u200B"));
0568         };
0569 
0570         const QDir privateResourceDir(folderInPrivateAppData);
0571         const QDir appDataDir(folderInStandardAppData);
0572         grpWindowsAppData->setPixmap(
0573             grpWindowsAppData->style()->standardIcon(QStyle::SP_MessageBoxInformation).pixmap(QSize(32, 32)));
0574         // Similar text is also used in KisViewManager.cpp
0575         grpWindowsAppData->setText(i18nc("@info resource folder",
0576                                          "<p>You are using the Microsoft Store package version of Krita. "
0577                                          "Even though Krita can be configured to place resources under the "
0578                                          "user AppData location, Windows may actually store the files "
0579                                          "inside a private app location.</p>\n"
0580                                          "<p>You should check both locations to determine where "
0581                                          "the files are located.</p>\n"
0582                                          "<p><b>User AppData</b> (<a href=\"copyuser\">Copy</a>):<br/>\n"
0583                                          "%1</p>\n"
0584                                          "<p><b>Private app location</b> (<a href=\"copyprivate\">Copy</a>):<br/>\n"
0585                                          "%2</p>",
0586                                          pathToDisplay(appDataDir.absolutePath()),
0587                                          pathToDisplay(privateResourceDir.absolutePath())));
0588         grpWindowsAppData->setVisible(true);
0589 
0590         connect(grpWindowsAppData,
0591                 &KisWarningBlock::linkActivated,
0592                 [userPath = appDataDir.absolutePath(),
0593                  privatePath = privateResourceDir.absolutePath()](const QString &link) {
0594                     if (link == QStringLiteral("copyuser")) {
0595                         qApp->clipboard()->setText(QDir::toNativeSeparators(userPath));
0596                     } else if (link == QStringLiteral("copyprivate")) {
0597                         qApp->clipboard()->setText(QDir::toNativeSeparators(privatePath));
0598                     } else {
0599                         qWarning() << "Unexpected link activated in lblWindowsAppDataNote:" << link;
0600                     }
0601                 });
0602     }
0603 #endif
0604 
0605 
0606     const int forcedFontDPI = cfg.readEntry("forcedDpiForQtFontBugWorkaround", -1);
0607     chkForcedFontDPI->setChecked(forcedFontDPI > 0);
0608     intForcedFontDPI->setValue(forcedFontDPI > 0 ? forcedFontDPI : qt_defaultDpi());
0609     intForcedFontDPI->setEnabled(forcedFontDPI > 0);
0610     connect(chkForcedFontDPI, SIGNAL(toggled(bool)), intForcedFontDPI, SLOT(setEnabled(bool)));
0611 
0612     m_pasteFormatGroup.addButton(btnDownload, KisClipboard::PASTE_FORMAT_DOWNLOAD);
0613     m_pasteFormatGroup.addButton(btnLocal, KisClipboard::PASTE_FORMAT_LOCAL);
0614     m_pasteFormatGroup.addButton(btnBitmap, KisClipboard::PASTE_FORMAT_CLIP);
0615     m_pasteFormatGroup.addButton(btnAsk, KisClipboard::PASTE_FORMAT_ASK);
0616 
0617     QAbstractButton *button = m_pasteFormatGroup.button(cfg.pasteFormat(false));
0618 
0619     Q_ASSERT(button);
0620 
0621     if (button) {
0622         button->setChecked(true);
0623     }
0624 }
0625 
0626 void GeneralTab::setDefault()
0627 {
0628     KisConfig cfg(true);
0629 
0630     m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle(true));
0631     m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle(true));
0632     m_chkSeparateEraserCursor->setChecked(cfg.readEntry<bool>("separateEraserCursor", false));
0633     m_cmbEraserCursorShape->setCurrentIndex(cfg.eraserCursorStyle(true));
0634     m_cmbEraserOutlineShape->setCurrentIndex(cfg.eraserOutlineStyle(true));
0635 
0636     chkShowRootLayer->setChecked(cfg.showRootLayer(true));
0637     m_autosaveCheckBox->setChecked(cfg.autoSaveInterval(true) > 0);
0638     //convert to minutes
0639     m_autosaveSpinBox->setValue(cfg.autoSaveInterval(true) / 60);
0640     chkHideAutosaveFiles->setChecked(true);
0641 
0642     m_undoStackSize->setValue(cfg.undoStackLimit(true));
0643     chkCumulativeUndo->setChecked(cfg.useCumulativeUndoRedo(true));
0644     m_cumulativeUndoData = cfg.cumulativeUndoData(true);
0645 
0646     m_backupFileCheckBox->setChecked(cfg.backupFile(true));
0647     cmbBackupFileLocation->setCurrentIndex(0);
0648     txtBackupFileSuffix->setText("~");
0649     intNumBackupFiles->setValue(1);
0650 
0651     m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting(true));
0652     m_changeBrushOutline->setChecked(!cfg.forceAlwaysFullSizedOutline(true));
0653     m_showEraserOutlinePainting->setChecked(cfg.showEraserOutlineWhilePainting(true));
0654     m_changeEraserBrushOutline->setChecked(!cfg.forceAlwaysFullSizedEraserOutline(true));
0655 
0656 #if defined Q_OS_ANDROID || defined Q_OS_MACOS || defined Q_OS_WIN
0657     m_chkNativeFileDialog->setChecked(true);
0658 #else
0659     m_chkNativeFileDialog->setChecked(false);
0660 #endif
0661 
0662     intMaxBrushSize->setValue(1000);
0663 
0664     chkUseCustomFont->setChecked(false);
0665     cmbCustomFont->setCurrentFont(qApp->font());
0666     intFontSize->setValue(qApp->font().pointSize());
0667 
0668         
0669     m_cmbMDIType->setCurrentIndex((int)QMdiArea::TabbedView);
0670     m_chkRubberBand->setChecked(cfg.useOpenGL(true));
0671     KoColor mdiColor;
0672     mdiColor.fromXML(cfg.getMDIBackgroundColor(true));
0673     m_mdiColor->setColor(mdiColor);
0674     m_backgroundimage->setText(cfg.getMDIBackgroundImage(true));
0675     m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true));
0676     m_chkCompressKra->setChecked(cfg.compressKra(true));
0677     m_chkTrimKra->setChecked(cfg.trimKra(true));
0678     m_chkTrimFramesImport->setChecked(cfg.trimFramesImport(true));
0679     chkZip64->setChecked(cfg.useZip64(true));
0680     m_chkHiDPI->setChecked(true);
0681 #ifdef HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY
0682     m_chkHiDPIFractionalScaling->setChecked(true);
0683 #endif
0684     chkUsageLogging->setChecked(true);
0685     m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true));
0686     cmbFlowMode->setCurrentIndex(0);
0687     m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled(true));
0688     m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture(true));
0689     spnZoomSteps->setValue(cfg.zoomSteps(true));
0690     m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity(true));
0691     m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars(true));
0692     intZoomMarginSize->setValue(cfg.zoomMarginSize(true));
0693     m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true));
0694     chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas(true));
0695     chkEnableTransformToolAfterPaste->setChecked(cfg.activateTransformToolAfterPaste(true));
0696     chkZoomHorizontally->setChecked(cfg.zoomHorizontal(true));
0697     m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true));
0698 
0699     KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8());
0700     cursorColor.fromQColor(cfg.getCursorMainColor(true));
0701     cursorColorButton->setColor(cursorColor);
0702 
0703     KoColor eraserCursorColor(KoColorSpaceRegistry::instance()->rgb8());
0704     eraserCursorColor.fromQColor(cfg.getEraserCursorMainColor(true));
0705     eraserCursorColorButton->setColor(eraserCursorColor);
0706 
0707 
0708     m_chkAutoPin->setChecked(cfg.autoPinLayersToTimeline(true));
0709     m_chkAdaptivePlaybackRange->setChecked(cfg.adaptivePlaybackRange(false));
0710 
0711     m_urlResourceFolder->setFileName(KoResourcePaths::getAppDataLocation());
0712 
0713     chkForcedFontDPI->setChecked(false);
0714     intForcedFontDPI->setValue(qt_defaultDpi());
0715     intForcedFontDPI->setEnabled(false);
0716 
0717     chkRenameMergedLayers->setChecked(KisImageConfig(true).renameMergedLayers(true));
0718     chkRenamePastedLayers->setChecked(cfg.renamePastedLayers(true));
0719 
0720     QAbstractButton *button = m_pasteFormatGroup.button(cfg.pasteFormat(true));
0721     Q_ASSERT(button);
0722 
0723     if (button) {
0724         button->setChecked(true);
0725     }
0726 }
0727 
0728 void GeneralTab::showAdvancedCumulativeUndoSettings()
0729 {
0730     KisDlgConfigureCumulativeUndo dlg(m_cumulativeUndoData, m_undoStackSize->value(), this);
0731     if (dlg.exec() == KoDialog::Accepted) {
0732         m_cumulativeUndoData = dlg.cumulativeUndoData();
0733     }
0734 }
0735 
0736 CursorStyle GeneralTab::cursorStyle()
0737 {
0738     return (CursorStyle)m_cmbCursorShape->currentIndex();
0739 }
0740 
0741 OutlineStyle GeneralTab::outlineStyle()
0742 {
0743     return (OutlineStyle)m_cmbOutlineShape->currentIndex();
0744 }
0745 
0746 CursorStyle GeneralTab::eraserCursorStyle()
0747 {
0748     return (CursorStyle)m_cmbEraserCursorShape->currentIndex();
0749 }
0750 
0751 OutlineStyle GeneralTab::eraserOutlineStyle()
0752 {
0753     return (OutlineStyle)m_cmbEraserOutlineShape->currentIndex();
0754 }
0755 
0756 KisConfig::SessionOnStartup GeneralTab::sessionOnStartup() const
0757 {
0758     return (KisConfig::SessionOnStartup)cmbStartupSession->currentIndex();
0759 }
0760 
0761 bool GeneralTab::saveSessionOnQuit() const
0762 {
0763     return chkSaveSessionOnQuit->isChecked();
0764 }
0765 
0766 bool GeneralTab::showRootLayer()
0767 {
0768     return chkShowRootLayer->isChecked();
0769 }
0770 
0771 int GeneralTab::autoSaveInterval()
0772 {
0773     //convert to seconds
0774     return m_autosaveCheckBox->isChecked() ? m_autosaveSpinBox->value() * 60 : 0;
0775 }
0776 
0777 int GeneralTab::undoStackSize()
0778 {
0779     return m_undoStackSize->value();
0780 }
0781 
0782 bool GeneralTab::showOutlineWhilePainting()
0783 {
0784     return m_showOutlinePainting->isChecked();
0785 }
0786 
0787 bool GeneralTab::showEraserOutlineWhilePainting()
0788 {
0789     return m_showEraserOutlinePainting->isChecked();
0790 }
0791 
0792 int GeneralTab::mdiMode()
0793 {
0794     return m_cmbMDIType->currentIndex();
0795 }
0796 
0797 bool GeneralTab::showCanvasMessages()
0798 {
0799     return m_chkCanvasMessages->isChecked();
0800 }
0801 
0802 bool GeneralTab::compressKra()
0803 {
0804     return m_chkCompressKra->isChecked();
0805 }
0806 
0807 bool GeneralTab::trimKra()
0808 {
0809     return m_chkTrimKra->isChecked();
0810 }
0811 
0812 bool GeneralTab::trimFramesImport()
0813 {
0814     return m_chkTrimFramesImport->isChecked();
0815 }
0816 
0817 bool GeneralTab::useZip64()
0818 {
0819     return chkZip64->isChecked();
0820 }
0821 
0822 bool GeneralTab::toolOptionsInDocker()
0823 {
0824     return m_radioToolOptionsInDocker->isChecked();
0825 }
0826 
0827 int GeneralTab::zoomSteps()
0828 {
0829     return spnZoomSteps->value();
0830 }
0831 
0832 bool GeneralTab::kineticScrollingEnabled()
0833 {
0834     return m_groupBoxKineticScrollingSettings->isChecked();
0835 }
0836 
0837 int GeneralTab::kineticScrollingGesture()
0838 {
0839     return m_cmbKineticScrollingGesture->currentIndex();
0840 }
0841 
0842 int GeneralTab::kineticScrollingSensitivity()
0843 {
0844     return m_kineticScrollingSensitivitySlider->value();
0845 }
0846 
0847 bool GeneralTab::kineticScrollingHiddenScrollbars()
0848 {
0849     return m_chkKineticScrollingHideScrollbars->isChecked();
0850 }
0851 
0852 int GeneralTab::zoomMarginSize()
0853 {
0854     return intZoomMarginSize->value();
0855 }
0856 
0857 bool GeneralTab::switchSelectionCtrlAlt()
0858 {
0859     return m_chkSwitchSelectionCtrlAlt->isChecked();
0860 }
0861 
0862 bool GeneralTab::convertToImageColorspaceOnImport()
0863 {
0864     return m_chkConvertOnImport->isChecked();
0865 }
0866 
0867 bool GeneralTab::autopinLayersToTimeline()
0868 {
0869     return m_chkAutoPin->isChecked();
0870 }
0871 
0872 bool GeneralTab::adaptivePlaybackRange()
0873 {
0874     return m_chkAdaptivePlaybackRange->isChecked();
0875 }
0876 
0877 int GeneralTab::forcedFontDpi()
0878 {
0879     return chkForcedFontDPI->isChecked() ? intForcedFontDPI->value() : -1;
0880 }
0881 
0882 bool GeneralTab::renameMergedLayers()
0883 {
0884     return chkRenameMergedLayers->isChecked();
0885 }
0886 
0887 bool GeneralTab::renamePastedLayers()
0888 {
0889     return chkRenamePastedLayers->isChecked();
0890 }
0891 
0892 void GeneralTab::getBackgroundImage()
0893 {
0894     KoFileDialog dialog(this, KoFileDialog::OpenFile, "BackgroundImages");
0895     dialog.setCaption(i18n("Select a Background Image"));
0896     dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
0897     dialog.setImageFilters();
0898 
0899     QString fn = dialog.filename();
0900     // dialog box was canceled or somehow no file was selected
0901     if (fn.isEmpty()) {
0902         return;
0903     }
0904 
0905     QImage image(fn);
0906     if (image.isNull()) {
0907         QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("%1 is not a valid image file!", fn));
0908     }
0909     else {
0910         m_backgroundimage->setText(fn);
0911     }
0912 }
0913 
0914 void GeneralTab::clearBackgroundImage()
0915 {
0916     // clearing the background image text will implicitly make the background color be used
0917     m_backgroundimage->setText("");
0918 }
0919 
0920 void GeneralTab::checkResourcePath()
0921 {
0922     const QFileInfo fi(m_urlResourceFolder->fileName());
0923     if (!fi.isWritable()) {
0924         grpNonWritableLocation->setPixmap(
0925             grpNonWritableLocation->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
0926         grpNonWritableLocation->setText(
0927             i18nc("@info resource folder", "<b>Warning:</b> this location is not writable."));
0928         grpNonWritableLocation->setVisible(true);
0929     } else {
0930         grpNonWritableLocation->setVisible(false);
0931     }
0932 }
0933 
0934 void GeneralTab::enableSubWindowOptions(int mdi_mode)
0935 {
0936     group_subWinMode->setEnabled(mdi_mode == QMdiArea::SubWindowView);
0937 }
0938 
0939 
0940 #include "kactioncollection.h"
0941 #include "KisActionsSnapshot.h"
0942 
0943 ShortcutSettingsTab::ShortcutSettingsTab(QWidget *parent, const char *name)
0944     : QWidget(parent)
0945 {
0946     setObjectName(name);
0947 
0948     QGridLayout * l = new QGridLayout(this);
0949     l->setMargin(0);
0950     m_page = new WdgShortcutSettings(this);
0951     l->addWidget(m_page, 0, 0);
0952 
0953 
0954     m_snapshot.reset(new KisActionsSnapshot);
0955 
0956     KisKActionCollection *collection =
0957         KisPart::instance()->currentMainwindow()->actionCollection();
0958 
0959     Q_FOREACH (QAction *action, collection->actions()) {
0960         m_snapshot->addAction(action->objectName(), action);
0961     }
0962 
0963     QMap<QString, KisKActionCollection*> sortedCollections =
0964         m_snapshot->actionCollections();
0965 
0966     for (auto it = sortedCollections.constBegin(); it != sortedCollections.constEnd(); ++it) {
0967         m_page->addCollection(it.value(), it.key());
0968     }
0969 }
0970 
0971 ShortcutSettingsTab::~ShortcutSettingsTab()
0972 {
0973 }
0974 
0975 void ShortcutSettingsTab::setDefault()
0976 {
0977     m_page->allDefault();
0978 }
0979 
0980 void ShortcutSettingsTab::saveChanges()
0981 {
0982     m_page->save();
0983     KisActionRegistry::instance()->settingsPageSaved();
0984 }
0985 
0986 void ShortcutSettingsTab::cancelChanges()
0987 {
0988     m_page->undo();
0989 }
0990 
0991 ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name)
0992     : QWidget(parent)
0993 {
0994     setObjectName(name);
0995 
0996     // XXX: Make sure only profiles that fit the specified color model
0997     // are shown in the profile combos
0998 
0999     QGridLayout * l = new QGridLayout(this);
1000     l->setMargin(0);
1001     m_page = new WdgColorSettings(this);
1002     l->addWidget(m_page, 0, 0);
1003 
1004     KisConfig cfg(true);
1005 
1006     m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile());
1007     connect(m_page->chkUseSystemMonitorProfile, SIGNAL(toggled(bool)), this, SLOT(toggleAllowMonitorProfileSelection(bool)));
1008 
1009     m_page->useDefColorSpace->setChecked(cfg.useDefaultColorSpace());
1010     connect(m_page->useDefColorSpace, SIGNAL(toggled(bool)), this, SLOT(toggleUseDefaultColorSpace(bool)));
1011     QList<KoID> colorSpaces = KoColorSpaceRegistry::instance()->listKeys();
1012     for (QList<KoID>::iterator id = colorSpaces.begin(); id != colorSpaces.end(); /* nop */) {
1013         if (KoColorSpaceRegistry::instance()->colorSpaceColorModelId(id->id()) == AlphaColorModelID) {
1014             id = colorSpaces.erase(id);
1015         } else {
1016             ++id;
1017         }
1018     }
1019     m_page->cmbWorkingColorSpace->setIDList(colorSpaces);
1020     m_page->cmbWorkingColorSpace->setCurrent(cfg.workingColorSpace());
1021     m_page->cmbWorkingColorSpace->setEnabled(cfg.useDefaultColorSpace());
1022 
1023     m_page->bnAddColorProfile->setIcon(koIcon("document-import-16"));
1024     connect(m_page->bnAddColorProfile, SIGNAL(clicked()), SLOT(installProfile()));
1025 
1026     QFormLayout *monitorProfileGrid = new QFormLayout(m_page->monitorprofileholder);
1027     monitorProfileGrid->setContentsMargins(0, 0, 0, 0);
1028     for(int i = 0; i < QGuiApplication::screens().count(); ++i) {
1029         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)));
1030         lbl->setWordWrap(true);
1031         m_monitorProfileLabels << lbl;
1032         KisSqueezedComboBox *cmb = new KisSqueezedComboBox();
1033         cmb->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
1034         monitorProfileGrid->addRow(lbl, cmb);
1035         m_monitorProfileWidgets << cmb;
1036     }
1037 
1038 // disable if not Linux as KisColorManager is not yet implemented outside Linux
1039 #ifndef Q_OS_LINUX
1040     m_page->chkUseSystemMonitorProfile->setChecked(false);
1041     m_page->chkUseSystemMonitorProfile->setDisabled(true);
1042     m_page->chkUseSystemMonitorProfile->setHidden(true);
1043 #endif
1044 
1045     refillMonitorProfiles(KoID("RGBA"));
1046 
1047     for(int i = 0; i < QApplication::screens().count(); ++i) {
1048         if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) {
1049             m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i));
1050         }
1051     }
1052 
1053     m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation());
1054     m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization());
1055     m_page->chkForcePaletteColor->setChecked(cfg.forcePaletteColors());
1056     KisImageConfig cfgImage(true);
1057 
1058     KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration();
1059     m_page->sldAdaptationState->setMaximum(20);
1060     m_page->sldAdaptationState->setMinimum(0);
1061     m_page->sldAdaptationState->setValue((int)proofingConfig->adaptationState*20);
1062 
1063     //probably this should become the screenprofile?
1064     KoColor ga(KoColorSpaceRegistry::instance()->rgb8());
1065     ga.fromKoColor(proofingConfig->warningColor);
1066     m_page->gamutAlarm->setColor(ga);
1067 
1068     const KoColorSpace *proofingSpace =  KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,
1069                                                                                       proofingConfig->proofingDepth,
1070                                                                                       proofingConfig->proofingProfile);
1071     if (proofingSpace) {
1072         m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace);
1073     }
1074 
1075     m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent);
1076     m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation));
1077 
1078     m_pasteBehaviourGroup.addButton(m_page->radioPasteWeb, KisClipboard::PASTE_ASSUME_WEB);
1079     m_pasteBehaviourGroup.addButton(m_page->radioPasteMonitor, KisClipboard::PASTE_ASSUME_MONITOR);
1080     m_pasteBehaviourGroup.addButton(m_page->radioPasteAsk, KisClipboard::PASTE_ASK);
1081 
1082     QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour());
1083     Q_ASSERT(button);
1084 
1085     if (button) {
1086         button->setChecked(true);
1087     }
1088 
1089     m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent());
1090 
1091     toggleAllowMonitorProfileSelection(cfg.useSystemMonitorProfile());
1092 
1093 }
1094 
1095 void ColorSettingsTab::installProfile()
1096 {
1097     KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC");
1098     dialog.setCaption(i18n("Install Color Profiles"));
1099     dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
1100     dialog.setMimeTypeFilters(QStringList() << "application/vnd.iccprofile", "application/vnd.iccprofile");
1101     QStringList profileNames = dialog.filenames();
1102 
1103     KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc");
1104     Q_ASSERT(iccEngine);
1105 
1106     QString saveLocation = KoResourcePaths::saveLocation("icc_profiles");
1107 
1108     Q_FOREACH (const QString &profileName, profileNames) {
1109         if (!QFile::copy(profileName, saveLocation + QFileInfo(profileName).fileName())) {
1110             qWarning() << "Could not install profile!" << saveLocation + QFileInfo(profileName).fileName();
1111             continue;
1112         }
1113         iccEngine->addProfile(saveLocation + QFileInfo(profileName).fileName());
1114     }
1115 
1116     KisConfig cfg(true);
1117     refillMonitorProfiles(KoID("RGBA"));
1118 
1119     for(int i = 0; i < QApplication::screens().count(); ++i) {
1120         if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) {
1121             m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i));
1122         }
1123     }
1124 
1125 }
1126 
1127 void ColorSettingsTab::toggleAllowMonitorProfileSelection(bool useSystemProfile)
1128 {
1129     KisConfig cfg(true);
1130 
1131     if (useSystemProfile) {
1132         QStringList devices = KisColorManager::instance()->devices();
1133         if (devices.size() == QApplication::screens().count()) {
1134             for(int i = 0; i < QApplication::screens().count(); ++i) {
1135                 m_monitorProfileWidgets[i]->clear();
1136                 QString monitorForScreen = cfg.monitorForScreen(i, devices[i]);
1137                 Q_FOREACH (const QString &device, devices) {
1138                     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)));
1139                     m_monitorProfileWidgets[i]->addSqueezedItem(KisColorManager::instance()->deviceName(device), device);
1140                     if (devices[i] == monitorForScreen) {
1141                         m_monitorProfileWidgets[i]->setCurrentIndex(i);
1142                     }
1143                 }
1144             }
1145         }
1146     }
1147     else {
1148         refillMonitorProfiles(KoID("RGBA"));
1149 
1150         for(int i = 0; i < QApplication::screens().count(); ++i) {
1151             if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) {
1152                 m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i));
1153             }
1154         }
1155     }
1156 }
1157 
1158 void ColorSettingsTab::toggleUseDefaultColorSpace(bool useDefColorSpace)
1159 {
1160     m_page->cmbWorkingColorSpace->setEnabled(useDefColorSpace);
1161 }
1162 
1163 void ColorSettingsTab::setDefault()
1164 {
1165     m_page->cmbWorkingColorSpace->setCurrent("RGBA");
1166 
1167     refillMonitorProfiles(KoID("RGBA"));
1168 
1169     KisConfig cfg(true);
1170     KisImageConfig cfgImage(true);
1171     KisProofingConfigurationSP proofingConfig =  cfgImage.defaultProofingconfiguration();
1172     const KoColorSpace *proofingSpace =  KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,proofingConfig->proofingDepth,proofingConfig->proofingProfile);
1173     if (proofingSpace) {
1174         m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace);
1175     }
1176     m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent);
1177     m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation));
1178     m_page->sldAdaptationState->setValue(0);
1179 
1180     //probably this should become the screenprofile?
1181     KoColor ga(KoColorSpaceRegistry::instance()->rgb8());
1182     ga.fromKoColor(proofingConfig->warningColor);
1183     m_page->gamutAlarm->setColor(ga);
1184 
1185     m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation(true));
1186     m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization(true));
1187     m_page->chkForcePaletteColor->setChecked(cfg.forcePaletteColors(true));
1188     m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent(true));
1189     m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile(true));
1190     QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour(true));
1191     Q_ASSERT(button);
1192     if (button) {
1193         button->setChecked(true);
1194     }
1195 }
1196 
1197 
1198 void ColorSettingsTab::refillMonitorProfiles(const KoID & colorSpaceId)
1199 {
1200     for (int i = 0; i < QApplication::screens().count(); ++i) {
1201         m_monitorProfileWidgets[i]->clear();
1202     }
1203 
1204     QMap<QString, const KoColorProfile *>  profileList;
1205     Q_FOREACH(const KoColorProfile *profile, KoColorSpaceRegistry::instance()->profilesFor(colorSpaceId.id())) {
1206         profileList[profile->name()] = profile;
1207     }
1208 
1209     Q_FOREACH (const KoColorProfile *profile, profileList.values()) {
1210         //qDebug() << "Profile" << profile->name() << profile->isSuitableForDisplay() << csf->defaultProfile();
1211         if (profile->isSuitableForDisplay()) {
1212             for (int i = 0; i < QApplication::screens().count(); ++i) {
1213                 m_monitorProfileWidgets[i]->addSqueezedItem(profile->name());
1214             }
1215         }
1216     }
1217 
1218     for (int i = 0; i < QApplication::screens().count(); ++i) {
1219         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)));
1220         m_monitorProfileWidgets[i]->setCurrent(KoColorSpaceRegistry::instance()->defaultProfileForColorSpace(colorSpaceId.id()));
1221     }
1222 }
1223 
1224 
1225 //---------------------------------------------------------------------------------------------------
1226 
1227 void TabletSettingsTab::setDefault()
1228 {
1229     KisConfig cfg(true);
1230     const KisCubicCurve curve(DEFAULT_CURVE_STRING);
1231     m_page->pressureCurve->setCurve(curve);
1232 
1233     m_page->chkUseRightMiddleClickWorkaround->setChecked(
1234         KisConfig(true).useRightMiddleTabletButtonWorkaround(true));
1235 
1236 #if defined Q_OS_WIN && (!defined USE_QT_TABLET_WINDOWS || defined QT_HAS_WINTAB_SWITCH)
1237 
1238 #ifdef USE_QT_TABLET_WINDOWS
1239     // ask Qt if WinInk is actually available
1240     const bool isWinInkAvailable = true;
1241 #else
1242     const bool isWinInkAvailable = KisTabletSupportWin8::isAvailable();
1243 #endif
1244     if (isWinInkAvailable) {
1245         m_page->radioWintab->setChecked(!cfg.useWin8PointerInput(true));
1246         m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput(true));
1247     } else {
1248         m_page->radioWintab->setChecked(true);
1249         m_page->radioWin8PointerInput->setChecked(false);
1250     }
1251 #else
1252         m_page->grpTabletApi->setVisible(false);
1253 #endif
1254 
1255     m_page->chkUseTimestampsForBrushSpeed->setChecked(false);
1256     m_page->intMaxAllowedBrushSpeed->setValue(30);
1257     m_page->intBrushSpeedSmoothing->setValue(3);
1258 
1259 }
1260 
1261 TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget(parent)
1262 {
1263     setObjectName(name);
1264 
1265     QGridLayout * l = new QGridLayout(this);
1266     l->setMargin(0);
1267     m_page = new WdgTabletSettings(this);
1268     l->addWidget(m_page, 0, 0);
1269 
1270     KisConfig cfg(true);
1271     const KisCubicCurve curve(cfg.pressureTabletCurve());
1272     m_page->pressureCurve->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
1273     m_page->pressureCurve->setCurve(curve);
1274 
1275     m_page->chkUseRightMiddleClickWorkaround->setChecked(
1276          cfg.useRightMiddleTabletButtonWorkaround());
1277 
1278 #if defined Q_OS_WIN && (!defined USE_QT_TABLET_WINDOWS || defined QT_HAS_WINTAB_SWITCH)
1279 #ifdef USE_QT_TABLET_WINDOWS
1280     // ask Qt if WinInk is actually available
1281     const bool isWinInkAvailable = true;
1282 #else
1283     const bool isWinInkAvailable = KisTabletSupportWin8::isAvailable();
1284 #endif
1285     if (isWinInkAvailable) {
1286         m_page->radioWintab->setChecked(!cfg.useWin8PointerInput());
1287         m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput());
1288     } else {
1289         m_page->radioWintab->setChecked(true);
1290         m_page->radioWin8PointerInput->setChecked(false);
1291         m_page->grpTabletApi->setVisible(false);
1292     }
1293 
1294 #ifdef USE_QT_TABLET_WINDOWS
1295     connect(m_page->btnResolutionSettings, SIGNAL(clicked()), SLOT(slotResolutionSettings()));
1296     connect(m_page->radioWintab, SIGNAL(toggled(bool)), m_page->btnResolutionSettings, SLOT(setEnabled(bool)));
1297     m_page->btnResolutionSettings->setEnabled(m_page->radioWintab->isChecked());
1298 #else
1299     m_page->btnResolutionSettings->setVisible(false);
1300 #endif
1301 
1302 #else
1303     m_page->grpTabletApi->setVisible(false);
1304 #endif
1305     connect(m_page->btnTabletTest, SIGNAL(clicked()), SLOT(slotTabletTest()));
1306 
1307 #ifdef Q_OS_WIN
1308     m_page->chkUseTimestampsForBrushSpeed->setText(i18n("Use tablet driver timestamps for brush speed (may cause severe artifacts when using WinTab tablet API)"));
1309 #else
1310     m_page->chkUseTimestampsForBrushSpeed->setText(i18n("Use tablet driver timestamps for brush speed"));
1311 #endif
1312     m_page->chkUseTimestampsForBrushSpeed->setChecked(cfg.readEntry("useTimestampsForBrushSpeed", false));
1313 
1314     m_page->intMaxAllowedBrushSpeed->setRange(1, 100);
1315     m_page->intMaxAllowedBrushSpeed->setValue(cfg.readEntry("maxAllowedSpeedValue", 30));
1316     KisSpinBoxI18nHelper::install(m_page->intMaxAllowedBrushSpeed, [](int value) {
1317         // i18n: This is meant to be used in a spinbox so keep the {n} in the text
1318         //       and it will be substituted by the number. The text before will be
1319         //       used as the prefix and the text after as the suffix
1320         return i18np("Maximum brush speed: {n} px/ms", "Maximum brush speed: {n} px/ms", value);
1321     });
1322 
1323     m_page->intBrushSpeedSmoothing->setRange(3, 100);
1324     m_page->intBrushSpeedSmoothing->setValue(cfg.readEntry("speedValueSmoothing", 3));
1325     KisSpinBoxI18nHelper::install(m_page->intBrushSpeedSmoothing, [](int value) {
1326         // i18n: This is meant to be used in a spinbox so keep the {n} in the text
1327         //       and it will be substituted by the number. The text before will be
1328         //       used as the prefix and the text after as the suffix
1329         return i18np("Brush speed smoothing: {n} sample", "Brush speed smoothing: {n} samples", value);
1330     });
1331 }
1332 
1333 void TabletSettingsTab::slotTabletTest()
1334 {
1335     TabletTestDialog tabletTestDialog(this);
1336     tabletTestDialog.exec();
1337 }
1338 
1339 #if defined Q_OS_WIN && defined USE_QT_TABLET_WINDOWS
1340 #include "KisDlgCustomTabletResolution.h"
1341 #endif
1342 
1343 void TabletSettingsTab::slotResolutionSettings()
1344 {
1345 #if defined Q_OS_WIN && defined USE_QT_TABLET_WINDOWS
1346     KisDlgCustomTabletResolution dlg(this);
1347     dlg.exec();
1348 #endif
1349 }
1350 
1351 
1352 //---------------------------------------------------------------------------------------------------
1353 #include "kis_acyclic_signal_connector.h"
1354 
1355 int getTotalRAM()
1356 {
1357     return KisImageConfig(true).totalRAM();
1358 }
1359 
1360 int PerformanceTab::realTilesRAM()
1361 {
1362     return intMemoryLimit->value() - intPoolLimit->value();
1363 }
1364 
1365 PerformanceTab::PerformanceTab(QWidget *parent, const char *name)
1366     : WdgPerformanceSettings(parent, name)
1367 {
1368     KisImageConfig cfg(true);
1369     const double totalRAM = cfg.totalRAM();
1370     lblTotalMemory->setText(KFormat().formatByteSize(totalRAM * 1024 * 1024, 0, KFormat::IECBinaryDialect, KFormat::UnitMegaByte));
1371 
1372     KisSpinBoxI18nHelper::setText(sliderMemoryLimit, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
1373     sliderMemoryLimit->setRange(1, 100, 2);
1374     sliderMemoryLimit->setSingleStep(0.01);
1375 
1376     KisSpinBoxI18nHelper::setText(sliderPoolLimit, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
1377     sliderPoolLimit->setRange(0, 20, 2);
1378     sliderPoolLimit->setSingleStep(0.01);
1379 
1380     KisSpinBoxI18nHelper::setText(sliderUndoLimit, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
1381     sliderUndoLimit->setRange(0, 50, 2);
1382     sliderUndoLimit->setSingleStep(0.01);
1383 
1384     intMemoryLimit->setMinimumWidth(80);
1385     intPoolLimit->setMinimumWidth(80);
1386     intUndoLimit->setMinimumWidth(80);
1387 
1388     {
1389         formLayout->takeRow(2);
1390         label_5->setVisible(false);
1391         intPoolLimit->setVisible(false);
1392         sliderPoolLimit->setVisible(false);
1393     }
1394 
1395     SliderAndSpinBoxSync *sync1 =
1396         new SliderAndSpinBoxSync(sliderMemoryLimit,
1397                                  intMemoryLimit,
1398                                  getTotalRAM);
1399 
1400     sync1->slotParentValueChanged();
1401     m_syncs << sync1;
1402 
1403     SliderAndSpinBoxSync *sync2 =
1404         new SliderAndSpinBoxSync(sliderPoolLimit,
1405                                  intPoolLimit,
1406                                  std::bind(&KisIntParseSpinBox::value,
1407                                              intMemoryLimit));
1408 
1409 
1410     connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync2, SLOT(slotParentValueChanged()));
1411     sync2->slotParentValueChanged();
1412     m_syncs << sync2;
1413 
1414     SliderAndSpinBoxSync *sync3 =
1415         new SliderAndSpinBoxSync(sliderUndoLimit,
1416                                  intUndoLimit,
1417                                  std::bind(&PerformanceTab::realTilesRAM,
1418                                              this));
1419 
1420 
1421     connect(intPoolLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged()));
1422     connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged()));
1423     sync3->slotParentValueChanged();
1424     m_syncs << sync3;
1425 
1426     sliderSwapSize->setSuffix(i18n(" GiB"));
1427     sliderSwapSize->setRange(1, 64);
1428     intSwapSize->setRange(1, 64);
1429 
1430 
1431     KisAcyclicSignalConnector *swapSizeConnector = new KisAcyclicSignalConnector(this);
1432 
1433     swapSizeConnector->connectForwardInt(sliderSwapSize, SIGNAL(valueChanged(int)),
1434                                          intSwapSize, SLOT(setValue(int)));
1435 
1436     swapSizeConnector->connectBackwardInt(intSwapSize, SIGNAL(valueChanged(int)),
1437                                           sliderSwapSize, SLOT(setValue(int)));
1438 
1439     swapFileLocation->setMode(KoFileDialog::OpenDirectory);
1440     swapFileLocation->setConfigurationName("swapfile_location");
1441     swapFileLocation->setFileName(cfg.swapDir());
1442 
1443     sliderThreadsLimit->setRange(1, QThread::idealThreadCount());
1444     sliderFrameClonesLimit->setRange(1, QThread::idealThreadCount());
1445 
1446     sliderFrameTimeout->setRange(5, 600);
1447     sliderFrameTimeout->setSuffix(i18nc("suffix for \"seconds\"", " sec"));
1448     sliderFrameTimeout->setValue(cfg.frameRenderingTimeout() / 1000);
1449 
1450     sliderFpsLimit->setRange(20, 300);
1451     sliderFpsLimit->setSuffix(i18n(" fps"));
1452 
1453     connect(sliderThreadsLimit, SIGNAL(valueChanged(int)), SLOT(slotThreadsLimitChanged(int)));
1454     connect(sliderFrameClonesLimit, SIGNAL(valueChanged(int)), SLOT(slotFrameClonesLimitChanged(int)));
1455 
1456     intCachedFramesSizeLimit->setRange(256, 10000);
1457     intCachedFramesSizeLimit->setSuffix(i18n(" px"));
1458     intCachedFramesSizeLimit->setSingleStep(1);
1459     intCachedFramesSizeLimit->setPageStep(1000);
1460 
1461     intRegionOfInterestMargin->setRange(1, 100);
1462     KisSpinBoxI18nHelper::setText(intRegionOfInterestMargin,
1463                                   i18nc("{n} is the number value, % is the percent sign", "{n}%"));
1464     intRegionOfInterestMargin->setSingleStep(1);
1465     intRegionOfInterestMargin->setPageStep(10);
1466 
1467     connect(chkCachedFramesSizeLimit, SIGNAL(toggled(bool)), intCachedFramesSizeLimit, SLOT(setEnabled(bool)));
1468     connect(chkUseRegionOfInterest, SIGNAL(toggled(bool)), intRegionOfInterestMargin, SLOT(setEnabled(bool)));
1469 
1470     connect(chkTransformToolUseInStackPreview, SIGNAL(toggled(bool)), chkTransformToolForceLodMode, SLOT(setEnabled(bool)));
1471 
1472 #ifndef Q_OS_WIN
1473     // AVX workaround is needed on Windows+GCC only
1474     chkDisableAVXOptimizations->setVisible(false);
1475 #endif
1476 
1477     load(false);
1478 }
1479 
1480 PerformanceTab::~PerformanceTab()
1481 {
1482     qDeleteAll(m_syncs);
1483 }
1484 
1485 void PerformanceTab::load(bool requestDefault)
1486 {
1487     KisImageConfig cfg(true);
1488 
1489     sliderMemoryLimit->setValue(cfg.memoryHardLimitPercent(requestDefault));
1490     sliderPoolLimit->setValue(cfg.memoryPoolLimitPercent(requestDefault));
1491     sliderUndoLimit->setValue(cfg.memorySoftLimitPercent(requestDefault));
1492 
1493     chkPerformanceLogging->setChecked(cfg.enablePerfLog(requestDefault));
1494     chkProgressReporting->setChecked(cfg.enableProgressReporting(requestDefault));
1495 
1496     sliderSwapSize->setValue(cfg.maxSwapSize(requestDefault) / 1024);
1497     swapFileLocation->setFileName(cfg.swapDir(requestDefault));
1498 
1499     m_lastUsedThreadsLimit = cfg.maxNumberOfThreads(requestDefault);
1500     m_lastUsedClonesLimit = cfg.frameRenderingClones(requestDefault);
1501 
1502     sliderThreadsLimit->setValue(m_lastUsedThreadsLimit);
1503     sliderFrameClonesLimit->setValue(m_lastUsedClonesLimit);
1504 
1505     sliderFpsLimit->setValue(cfg.fpsLimit(requestDefault));
1506 
1507     {
1508         KisConfig cfg2(true);
1509         chkOpenGLFramerateLogging->setChecked(cfg2.enableOpenGLFramerateLogging(requestDefault));
1510         chkBrushSpeedLogging->setChecked(cfg2.enableBrushSpeedLogging(requestDefault));
1511         chkDisableVectorOptimizations->setChecked(cfg2.disableVectorOptimizations(requestDefault));
1512 #ifdef Q_OS_WIN
1513         chkDisableAVXOptimizations->setChecked(cfg2.disableAVXOptimizations(requestDefault));
1514 #endif
1515         chkBackgroundCacheGeneration->setChecked(cfg2.calculateAnimationCacheInBackground(requestDefault));
1516     }
1517 
1518     if (cfg.useOnDiskAnimationCacheSwapping(requestDefault)) {
1519         optOnDisk->setChecked(true);
1520     } else {
1521         optInMemory->setChecked(true);
1522     }
1523 
1524     chkCachedFramesSizeLimit->setChecked(cfg.useAnimationCacheFrameSizeLimit(requestDefault));
1525     intCachedFramesSizeLimit->setValue(cfg.animationCacheFrameSizeLimit(requestDefault));
1526     intCachedFramesSizeLimit->setEnabled(chkCachedFramesSizeLimit->isChecked());
1527 
1528     chkUseRegionOfInterest->setChecked(cfg.useAnimationCacheRegionOfInterest(requestDefault));
1529     intRegionOfInterestMargin->setValue(cfg.animationCacheRegionOfInterestMargin(requestDefault) * 100.0);
1530     intRegionOfInterestMargin->setEnabled(chkUseRegionOfInterest->isChecked());
1531 
1532     {
1533         KConfigGroup group = KSharedConfig::openConfig()->group("KisToolTransform");
1534         chkTransformToolUseInStackPreview->setChecked(!group.readEntry("useOverlayPreviewStyle", false));
1535         chkTransformToolForceLodMode->setChecked(group.readEntry("forceLodMode", true));
1536         chkTransformToolForceLodMode->setEnabled(chkTransformToolUseInStackPreview->isChecked());
1537     }
1538 
1539     {
1540         KConfigGroup group = KSharedConfig::openConfig()->group("KritaTransform/KisToolMove");
1541         chkMoveToolForceLodMode->setChecked(group.readEntry("forceLodMode", false));
1542     }
1543 
1544     {
1545         KConfigGroup group( KSharedConfig::openConfig(), "filterdialog");
1546         chkFiltersForceLodMode->setChecked(group.readEntry("forceLodMode", true));
1547     }
1548 }
1549 
1550 void PerformanceTab::save()
1551 {
1552     KisImageConfig cfg(false);
1553 
1554     cfg.setMemoryHardLimitPercent(sliderMemoryLimit->value());
1555     cfg.setMemorySoftLimitPercent(sliderUndoLimit->value());
1556     cfg.setMemoryPoolLimitPercent(sliderPoolLimit->value());
1557 
1558     cfg.setEnablePerfLog(chkPerformanceLogging->isChecked());
1559     cfg.setEnableProgressReporting(chkProgressReporting->isChecked());
1560 
1561     cfg.setMaxSwapSize(sliderSwapSize->value() * 1024);
1562 
1563     cfg.setSwapDir(swapFileLocation->fileName());
1564 
1565     cfg.setMaxNumberOfThreads(sliderThreadsLimit->value());
1566     cfg.setFrameRenderingClones(sliderFrameClonesLimit->value());
1567     cfg.setFrameRenderingTimeout(sliderFrameTimeout->value() * 1000);
1568     cfg.setFpsLimit(sliderFpsLimit->value());
1569 
1570     {
1571         KisConfig cfg2(true);
1572         cfg2.setEnableOpenGLFramerateLogging(chkOpenGLFramerateLogging->isChecked());
1573         cfg2.setEnableBrushSpeedLogging(chkBrushSpeedLogging->isChecked());
1574         cfg2.setDisableVectorOptimizations(chkDisableVectorOptimizations->isChecked());
1575 #ifdef Q_OS_WIN
1576         cfg2.setDisableAVXOptimizations(chkDisableAVXOptimizations->isChecked());
1577 #endif
1578         cfg2.setCalculateAnimationCacheInBackground(chkBackgroundCacheGeneration->isChecked());
1579     }
1580 
1581     cfg.setUseOnDiskAnimationCacheSwapping(optOnDisk->isChecked());
1582 
1583     cfg.setUseAnimationCacheFrameSizeLimit(chkCachedFramesSizeLimit->isChecked());
1584     cfg.setAnimationCacheFrameSizeLimit(intCachedFramesSizeLimit->value());
1585 
1586     cfg.setUseAnimationCacheRegionOfInterest(chkUseRegionOfInterest->isChecked());
1587     cfg.setAnimationCacheRegionOfInterestMargin(intRegionOfInterestMargin->value() / 100.0);
1588 
1589     {
1590         KConfigGroup group = KSharedConfig::openConfig()->group("KisToolTransform");
1591         group.writeEntry("useOverlayPreviewStyle", !chkTransformToolUseInStackPreview->isChecked());
1592         group.writeEntry("forceLodMode", chkTransformToolForceLodMode->isChecked());
1593     }
1594 
1595     {
1596         KConfigGroup group = KSharedConfig::openConfig()->group("KritaTransform/KisToolMove");
1597         group.writeEntry("forceLodMode", chkMoveToolForceLodMode->isChecked());
1598     }
1599 
1600     {
1601         KConfigGroup group( KSharedConfig::openConfig(), "filterdialog");
1602         group.writeEntry("forceLodMode", chkFiltersForceLodMode->isChecked());
1603     }
1604 
1605 }
1606 
1607 void PerformanceTab::slotThreadsLimitChanged(int value)
1608 {
1609     KisSignalsBlocker b(sliderFrameClonesLimit);
1610     sliderFrameClonesLimit->setValue(qMin(m_lastUsedClonesLimit, value));
1611     m_lastUsedThreadsLimit = value;
1612 }
1613 
1614 void PerformanceTab::slotFrameClonesLimitChanged(int value)
1615 {
1616     KisSignalsBlocker b(sliderThreadsLimit);
1617     sliderThreadsLimit->setValue(qMax(m_lastUsedThreadsLimit, value));
1618     m_lastUsedClonesLimit = value;
1619 }
1620 
1621 //---------------------------------------------------------------------------------------------------
1622 
1623 #include "KoColor.h"
1624 #include "opengl/KisOpenGLModeProber.h"
1625 #include "opengl/KisScreenInformationAdapter.h"
1626 #include <QOpenGLContext>
1627 #include <QScreen>
1628 
1629 namespace {
1630 
1631 QString colorSpaceString(KisSurfaceColorSpace cs, int depth)
1632 {
1633     const QString csString =
1634 #ifdef HAVE_HDR
1635         cs == KisSurfaceColorSpace::bt2020PQColorSpace ? "Rec. 2020 PQ" :
1636         cs == KisSurfaceColorSpace::scRGBColorSpace ? "Rec. 709 Linear" :
1637 #endif
1638         cs == KisSurfaceColorSpace::sRGBColorSpace ? "sRGB" :
1639         cs == KisSurfaceColorSpace::DefaultColorSpace ? "sRGB" :
1640         "Unknown Color Space";
1641 
1642     return QString("%1 (%2 bit)").arg(csString).arg(depth);
1643 }
1644 
1645 int formatToIndex(KisConfig::RootSurfaceFormat fmt)
1646 {
1647     return fmt == KisConfig::BT2020_PQ ? 1 :
1648            fmt == KisConfig::BT709_G10 ? 2 :
1649            0;
1650 }
1651 
1652 KisConfig::RootSurfaceFormat indexToFormat(int value)
1653 {
1654     return value == 1 ? KisConfig::BT2020_PQ :
1655            value == 2 ? KisConfig::BT709_G10 :
1656            KisConfig::BT709_G22;
1657 }
1658 
1659 int assistantDrawModeToIndex(KisConfig::AssistantsDrawMode mode)
1660 {
1661     return mode == KisConfig::ASSISTANTS_DRAW_MODE_PIXMAP_CACHE ? 1 :
1662            mode == KisConfig::ASSISTANTS_DRAW_MODE_LARGE_PIXMAP_CACHE ? 2 :
1663            0;
1664 }
1665 
1666 KisConfig::AssistantsDrawMode indexToAssistantDrawMode(int value)
1667 {
1668     return value == 1 ? KisConfig::ASSISTANTS_DRAW_MODE_PIXMAP_CACHE :
1669            value == 2 ? KisConfig::ASSISTANTS_DRAW_MODE_LARGE_PIXMAP_CACHE :
1670            KisConfig::ASSISTANTS_DRAW_MODE_DIRECT;
1671 }
1672 
1673 } // anonymous namespace
1674 
1675 DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name)
1676     : WdgDisplaySettings(parent, name)
1677 {
1678     KisConfig cfg(true);
1679 
1680     const QString rendererOpenGLText = i18nc("canvas renderer", "OpenGL");
1681     const QString rendererSoftwareText = i18nc("canvas renderer", "Software Renderer (very slow)");
1682 #ifdef Q_OS_WIN
1683     const QString rendererOpenGLESText = i18nc("canvas renderer", "Direct3D 11 via ANGLE");
1684 #else
1685     const QString rendererOpenGLESText = i18nc("canvas renderer", "OpenGL ES");
1686 #endif
1687 
1688     const KisOpenGL::OpenGLRenderer renderer = KisOpenGL::getCurrentOpenGLRenderer();
1689     lblCurrentRenderer->setText(renderer == KisOpenGL::RendererOpenGLES ? rendererOpenGLESText :
1690                                 renderer == KisOpenGL::RendererDesktopGL ? rendererOpenGLText :
1691                                 renderer == KisOpenGL::RendererSoftware ? rendererSoftwareText :
1692                                 i18nc("canvas renderer", "Unknown"));
1693 
1694     cmbPreferredRenderer->clear();
1695 
1696     const KisOpenGL::OpenGLRenderers supportedRenderers = KisOpenGL::getSupportedOpenGLRenderers();
1697     const bool onlyOneRendererSupported =
1698         supportedRenderers == KisOpenGL::RendererDesktopGL ||
1699         supportedRenderers == KisOpenGL::RendererOpenGLES ||
1700         supportedRenderers == KisOpenGL::RendererSoftware;
1701 
1702 
1703     if (!onlyOneRendererSupported) {
1704         QString qtPreferredRendererText;
1705         if (KisOpenGL::getQtPreferredOpenGLRenderer() == KisOpenGL::RendererOpenGLES) {
1706             qtPreferredRendererText = rendererOpenGLESText;
1707         } else if (KisOpenGL::getQtPreferredOpenGLRenderer() == KisOpenGL::RendererSoftware) {
1708             qtPreferredRendererText = rendererSoftwareText;
1709         } else {
1710             qtPreferredRendererText = rendererOpenGLText;
1711         }
1712         cmbPreferredRenderer->addItem(i18nc("canvas renderer", "Auto (%1)", qtPreferredRendererText), KisOpenGL::RendererAuto);
1713         cmbPreferredRenderer->setCurrentIndex(0);
1714     } else {
1715         cmbPreferredRenderer->setEnabled(false);
1716     }
1717 
1718     if (supportedRenderers & KisOpenGL::RendererDesktopGL) {
1719         cmbPreferredRenderer->addItem(rendererOpenGLText, KisOpenGL::RendererDesktopGL);
1720         if (KisOpenGL::getUserPreferredOpenGLRendererConfig() == KisOpenGL::RendererDesktopGL) {
1721             cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1);
1722         }
1723     }
1724 
1725     if (supportedRenderers & KisOpenGL::RendererOpenGLES) {
1726         cmbPreferredRenderer->addItem(rendererOpenGLESText, KisOpenGL::RendererOpenGLES);
1727         if (KisOpenGL::getUserPreferredOpenGLRendererConfig() == KisOpenGL::RendererOpenGLES) {
1728             cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1);
1729         }
1730     }
1731 
1732     if (supportedRenderers & KisOpenGL::RendererSoftware) {
1733         cmbPreferredRenderer->addItem(rendererSoftwareText, KisOpenGL::RendererSoftware);
1734         if (KisOpenGL::getUserPreferredOpenGLRendererConfig() == KisOpenGL::RendererSoftware) {
1735             cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1);
1736         }
1737     }
1738 
1739     if (!(supportedRenderers &
1740           (KisOpenGL::RendererDesktopGL |
1741            KisOpenGL::RendererOpenGLES |
1742            KisOpenGL::RendererSoftware))) {
1743 
1744         grpOpenGL->setEnabled(false);
1745         grpOpenGL->setChecked(false);
1746         chkUseTextureBuffer->setEnabled(false);
1747         cmbAssistantsDrawMode->setEnabled(false);
1748         cmbFilterMode->setEnabled(false);
1749     } else {
1750         grpOpenGL->setEnabled(true);
1751         grpOpenGL->setChecked(cfg.useOpenGL());
1752         chkUseTextureBuffer->setEnabled(cfg.useOpenGL());
1753         chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer());
1754         cmbAssistantsDrawMode->setEnabled(cfg.useOpenGL());
1755         cmbAssistantsDrawMode->setCurrentIndex(assistantDrawModeToIndex(cfg.assistantsDrawMode()));
1756         cmbFilterMode->setEnabled(cfg.useOpenGL());
1757         cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode());
1758         // Don't show the high quality filtering mode if it's not available
1759         if (!KisOpenGL::supportsLoD()) {
1760             cmbFilterMode->removeItem(3);
1761         }
1762     }
1763 
1764     lblCurrentDisplayFormat->setText("");
1765     lblCurrentRootSurfaceFormat->setText("");
1766     grpHDRWarning->setVisible(false);
1767     cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(KisSurfaceColorSpace::sRGBColorSpace, 8));
1768 #ifdef HAVE_HDR
1769     cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(KisSurfaceColorSpace::bt2020PQColorSpace, 10));
1770     cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(KisSurfaceColorSpace::scRGBColorSpace, 16));
1771 #endif
1772     cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(KisConfig::BT709_G22));
1773     slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex());
1774 
1775     QOpenGLContext *context = QOpenGLContext::currentContext();
1776 
1777     if (!context) {
1778         context = QOpenGLContext::globalShareContext();
1779     }
1780 
1781     if (context) {
1782 #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
1783         QScreen *screen = QGuiApplication::screenAt(rect().center());
1784 #else
1785         QScreen *screen = 0;
1786 #endif
1787         KisScreenInformationAdapter adapter(context);
1788         if (screen && adapter.isValid()) {
1789             KisScreenInformationAdapter::ScreenInfo info = adapter.infoForScreen(screen);
1790             if (info.isValid()) {
1791                 QStringList toolTip;
1792 
1793                 toolTip << i18n("Display Id: %1", info.screen->name());
1794                 toolTip << i18n("Display Name: %1 %2", info.screen->manufacturer(), info.screen->model());
1795                 toolTip << i18n("Min Luminance: %1", info.minLuminance);
1796                 toolTip << i18n("Max Luminance: %1", info.maxLuminance);
1797                 toolTip << i18n("Max Full Frame Luminance: %1", info.maxFullFrameLuminance);
1798                 toolTip << i18n("Red Primary: %1, %2", info.redPrimary[0], info.redPrimary[1]);
1799                 toolTip << i18n("Green Primary: %1, %2", info.greenPrimary[0], info.greenPrimary[1]);
1800                 toolTip << i18n("Blue Primary: %1, %2", info.bluePrimary[0], info.bluePrimary[1]);
1801                 toolTip << i18n("White Point: %1, %2", info.whitePoint[0], info.whitePoint[1]);
1802 
1803                 lblCurrentDisplayFormat->setToolTip(toolTip.join('\n'));
1804                 lblCurrentDisplayFormat->setText(colorSpaceString(info.colorSpace, info.bitsPerColor));
1805             } else {
1806                 lblCurrentDisplayFormat->setToolTip("");
1807                 lblCurrentDisplayFormat->setText(i18n("Unknown"));
1808             }
1809         } else {
1810             lblCurrentDisplayFormat->setToolTip("");
1811             lblCurrentDisplayFormat->setText(i18n("Unknown"));
1812             qWarning() << "Failed to fetch display info:" << adapter.errorString();
1813         }
1814 
1815         const QSurfaceFormat currentFormat = KisOpenGLModeProber::instance()->surfaceformatInUse();
1816 #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
1817         KisSurfaceColorSpace colorSpace = currentFormat.colorSpace();
1818 #else
1819         KisSurfaceColorSpace colorSpace = KisSurfaceColorSpace::DefaultColorSpace;
1820 #endif
1821         lblCurrentRootSurfaceFormat->setText(colorSpaceString(colorSpace, currentFormat.redBufferSize()));
1822         cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(cfg.rootSurfaceFormat()));
1823         connect(cmbPreferedRootSurfaceFormat, SIGNAL(currentIndexChanged(int)), SLOT(slotPreferredSurfaceFormatChanged(int)));
1824         slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex());
1825     }
1826 
1827 #ifndef HAVE_HDR
1828     tabHDR->setEnabled(false);
1829 #endif
1830 
1831     const QStringList openglWarnings = KisOpenGL::getOpenGLWarnings();
1832     if (openglWarnings.isEmpty()) {
1833         grpOpenGLWarnings->setVisible(false);
1834     } else {
1835         QString text = QString("<p><b>%1</b>").arg(i18n("Warning(s):"));
1836         text.append("<ul>");
1837         Q_FOREACH (const QString &warning, openglWarnings) {
1838             text.append("<li>");
1839             text.append(warning.toHtmlEscaped());
1840             text.append("</li>");
1841         }
1842         text.append("</ul></p>");
1843         grpOpenGLWarnings->setText(text);
1844         grpOpenGLWarnings->setPixmap(
1845             grpOpenGLWarnings->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
1846         grpOpenGLWarnings->setVisible(true);
1847     }
1848 
1849     if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") {
1850        grpOpenGL->setVisible(false);
1851        grpOpenGL->setMaximumHeight(0);
1852     }
1853 
1854     KisImageConfig imageCfg(false);
1855 
1856     KoColor c;
1857     c.fromQColor(imageCfg.selectionOverlayMaskColor());
1858     c.setOpacity(1.0);
1859     btnSelectionOverlayColor->setColor(c);
1860     sldSelectionOverlayOpacity->setRange(0.0, 1.0, 2);
1861     sldSelectionOverlayOpacity->setSingleStep(0.05);
1862     sldSelectionOverlayOpacity->setValue(imageCfg.selectionOverlayMaskColor().alphaF());
1863 
1864     sldSelectionOutlineOpacity->setRange(0.0, 1.0, 2);
1865     sldSelectionOutlineOpacity->setSingleStep(0.05);
1866     sldSelectionOutlineOpacity->setValue(imageCfg.selectionOutlineOpacity());
1867 
1868     intCheckSize->setValue(cfg.checkSize());
1869     chkMoving->setChecked(cfg.scrollCheckers());
1870     KoColor ck1(KoColorSpaceRegistry::instance()->rgb8());
1871     ck1.fromQColor(cfg.checkersColor1());
1872     colorChecks1->setColor(ck1);
1873     KoColor ck2(KoColorSpaceRegistry::instance()->rgb8());
1874     ck2.fromQColor(cfg.checkersColor2());
1875     colorChecks2->setColor(ck2);
1876     KoColor cb(KoColorSpaceRegistry::instance()->rgb8());
1877     cb.fromQColor(cfg.canvasBorderColor());
1878     canvasBorder->setColor(cb);
1879     hideScrollbars->setChecked(cfg.hideScrollbars());
1880     chkCurveAntialiasing->setChecked(cfg.antialiasCurves());
1881     chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline());
1882     chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor());
1883     chkHidePopups->setChecked(cfg.hidePopups());
1884 
1885     connect(grpOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool)));
1886 
1887     KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8());
1888     gridColor.fromQColor(cfg.getPixelGridColor());
1889     pixelGridColorButton->setColor(gridColor);
1890     pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold() * 100);
1891 }
1892 
1893 void DisplaySettingsTab::setDefault()
1894 {
1895     KisConfig cfg(true);
1896     cmbPreferredRenderer->setCurrentIndex(0);
1897     if (!(KisOpenGL::getSupportedOpenGLRenderers() &
1898             (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererOpenGLES))) {
1899         grpOpenGL->setEnabled(false);
1900         grpOpenGL->setChecked(false);
1901         chkUseTextureBuffer->setEnabled(false);
1902         cmbAssistantsDrawMode->setEnabled(false);
1903         cmbFilterMode->setEnabled(false);
1904     }
1905     else {
1906         grpOpenGL->setEnabled(true);
1907         grpOpenGL->setChecked(cfg.useOpenGL(true));
1908         chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer(true));
1909         chkUseTextureBuffer->setEnabled(true);
1910         cmbAssistantsDrawMode->setEnabled(true);
1911         cmbAssistantsDrawMode->setCurrentIndex(assistantDrawModeToIndex(cfg.assistantsDrawMode(true)));
1912         cmbFilterMode->setEnabled(true);
1913         cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode(true));
1914     }
1915 
1916     chkMoving->setChecked(cfg.scrollCheckers(true));
1917 
1918     KisImageConfig imageCfg(false);
1919 
1920     KoColor c;
1921     c.fromQColor(imageCfg.selectionOverlayMaskColor(true));
1922     c.setOpacity(1.0);
1923     btnSelectionOverlayColor->setColor(c);
1924     sldSelectionOverlayOpacity->setValue(imageCfg.selectionOverlayMaskColor(true).alphaF());
1925 
1926     sldSelectionOutlineOpacity->setValue(imageCfg.selectionOutlineOpacity(true));
1927 
1928     intCheckSize->setValue(cfg.checkSize(true));
1929     KoColor ck1(KoColorSpaceRegistry::instance()->rgb8());
1930     ck1.fromQColor(cfg.checkersColor1(true));
1931     colorChecks1->setColor(ck1);
1932     KoColor ck2(KoColorSpaceRegistry::instance()->rgb8());
1933     ck2.fromQColor(cfg.checkersColor2(true));
1934     colorChecks2->setColor(ck2);
1935     KoColor cvb(KoColorSpaceRegistry::instance()->rgb8());
1936     cvb.fromQColor(cfg.canvasBorderColor(true));
1937     canvasBorder->setColor(cvb);
1938     hideScrollbars->setChecked(cfg.hideScrollbars(true));
1939     chkCurveAntialiasing->setChecked(cfg.antialiasCurves(true));
1940     chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline(true));
1941     chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor(true));
1942     chkHidePopups->setChecked(cfg.hidePopups(true));
1943 
1944     KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8());
1945     gridColor.fromQColor(cfg.getPixelGridColor(true));
1946     pixelGridColorButton->setColor(gridColor);
1947     pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold(true) * 100);
1948 
1949     cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(KisConfig::BT709_G22));
1950     slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex());
1951 }
1952 
1953 void DisplaySettingsTab::slotUseOpenGLToggled(bool isChecked)
1954 {
1955     chkUseTextureBuffer->setEnabled(isChecked);
1956     cmbFilterMode->setEnabled(isChecked);
1957     cmbAssistantsDrawMode->setEnabled(isChecked);
1958 }
1959 
1960 void DisplaySettingsTab::slotPreferredSurfaceFormatChanged(int index)
1961 {
1962     Q_UNUSED(index);
1963 
1964     QOpenGLContext *context = QOpenGLContext::currentContext();
1965     if (context) {
1966 #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
1967         QScreen *screen = QGuiApplication::screenAt(rect().center());
1968 #else
1969         QScreen *screen = 0;
1970 #endif
1971         KisScreenInformationAdapter adapter(context);
1972         if (adapter.isValid()) {
1973             KisScreenInformationAdapter::ScreenInfo info = adapter.infoForScreen(screen);
1974             if (info.isValid()) {
1975                 if (cmbPreferedRootSurfaceFormat->currentIndex() != formatToIndex(KisConfig::BT709_G22) &&
1976                     info.colorSpace == KisSurfaceColorSpace::sRGBColorSpace) {
1977                     grpHDRWarning->setVisible(true);
1978                     grpHDRWarning->setPixmap(
1979                         grpHDRWarning->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
1980                     grpHDRWarning->setText(i18n("<b>Warning:</b> current display doesn't support HDR rendering"));
1981                 } else {
1982                     grpHDRWarning->setVisible(false);
1983                 }
1984             }
1985         }
1986     }
1987 }
1988 
1989 //---------------------------------------------------------------------------------------------------
1990 FullscreenSettingsTab::FullscreenSettingsTab(QWidget* parent) : WdgFullscreenSettingsBase(parent)
1991 {
1992     KisConfig cfg(true);
1993 
1994     chkDockers->setChecked(cfg.hideDockersFullscreen());
1995     chkMenu->setChecked(cfg.hideMenuFullscreen());
1996     chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen());
1997     chkStatusbar->setChecked(cfg.hideStatusbarFullscreen());
1998     chkTitlebar->setChecked(cfg.hideTitlebarFullscreen());
1999     chkToolbar->setChecked(cfg.hideToolbarFullscreen());
2000 
2001 }
2002 
2003 void FullscreenSettingsTab::setDefault()
2004 {
2005     KisConfig cfg(true);
2006     chkDockers->setChecked(cfg.hideDockersFullscreen(true));
2007     chkMenu->setChecked(cfg.hideMenuFullscreen(true));
2008     chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen(true));
2009     chkStatusbar->setChecked(cfg.hideStatusbarFullscreen(true));
2010     chkTitlebar->setChecked(cfg.hideTitlebarFullscreen(true));
2011     chkToolbar->setChecked(cfg.hideToolbarFullscreen(true));
2012 }
2013 
2014 
2015 //---------------------------------------------------------------------------------------------------
2016 
2017 PopupPaletteTab::PopupPaletteTab(QWidget *parent, const char *name)
2018     : WdgPopupPaletteSettingsBase(parent, name)
2019 {
2020     load();
2021 }
2022 
2023 void PopupPaletteTab::load()
2024 {
2025     KisConfig config(true);
2026     sbNumPresets->setValue(config.favoritePresets());
2027     sbPaletteSize->setValue(config.readEntry("popuppalette/size", 385));
2028     sbSelectorSize->setValue(config.readEntry("popuppalette/selectorSize", 140));
2029     cmbSelectorType->setCurrentIndex(config.readEntry<bool>("popuppalette/usevisualcolorselector", false) ? 1 : 0);
2030     chkShowColorHistory->setChecked(config.readEntry("popuppalette/showColorHistory", true));
2031     chkShowRotationTrack->setChecked(config.readEntry("popuppalette/showRotationTrack", true));
2032     chkUseDynamicSlotCount->setChecked(config.readEntry("popuppalette/useDynamicSlotCount", true));
2033 }
2034 
2035 void PopupPaletteTab::save()
2036 {
2037     KisConfig config(true);
2038     config.setFavoritePresets(sbNumPresets->value());
2039     config.writeEntry("popuppalette/size", sbPaletteSize->value());
2040     config.writeEntry("popuppalette/selectorSize", sbSelectorSize->value());
2041     config.writeEntry<bool>("popuppalette/usevisualcolorselector", cmbSelectorType->currentIndex() > 0);
2042     config.writeEntry<bool>("popuppalette/showColorHistory", chkShowColorHistory->isChecked());
2043     config.writeEntry<bool>("popuppalette/showRotationTrack", chkShowRotationTrack->isChecked());
2044     config.writeEntry<bool>("popuppalette/useDynamicSlotCount", chkUseDynamicSlotCount->isChecked());
2045 }
2046 
2047 void PopupPaletteTab::setDefault()
2048 {
2049     KisConfig config(true);
2050     sbNumPresets->setValue(config.favoritePresets(true));
2051     sbPaletteSize->setValue(385);
2052     sbSelectorSize->setValue(140);
2053     cmbSelectorType->setCurrentIndex(0);
2054     chkShowColorHistory->setChecked(true);
2055     chkShowRotationTrack->setChecked(true);
2056     chkUseDynamicSlotCount->setChecked(true);
2057 }
2058 
2059 //---------------------------------------------------------------------------------------------------
2060 
2061 KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name)
2062     : KPageDialog(parent)
2063 {
2064     Q_UNUSED(name);
2065     setWindowTitle(i18n("Configure Krita"));
2066     setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults);
2067 
2068     setFaceType(KPageDialog::List);
2069 
2070     // General
2071     KoVBox *vbox = new KoVBox();
2072     KPageWidgetItem *page = new KPageWidgetItem(vbox, i18n("General"));
2073     page->setObjectName("general");
2074     page->setHeader(i18n("General"));
2075     page->setIcon(KisIconUtils::loadIcon("config-general"));
2076     m_pages << page;
2077     addPage(page);
2078     m_general = new GeneralTab(vbox);
2079 
2080     // Shortcuts
2081     vbox = new KoVBox();
2082     page = new KPageWidgetItem(vbox, i18n("Keyboard Shortcuts"));
2083     page->setObjectName("shortcuts");
2084     page->setHeader(i18n("Shortcuts"));
2085     page->setIcon(KisIconUtils::loadIcon("config-keyboard"));
2086     m_pages << page;
2087     addPage(page);
2088     m_shortcutSettings = new ShortcutSettingsTab(vbox);
2089     connect(this, SIGNAL(accepted()), m_shortcutSettings, SLOT(saveChanges()));
2090     connect(this, SIGNAL(rejected()), m_shortcutSettings, SLOT(cancelChanges()));
2091 
2092     // Canvas input settings
2093     m_inputConfiguration = new KisInputConfigurationPage();
2094     page = addPage(m_inputConfiguration, i18n("Canvas Input Settings"));
2095     page->setHeader(i18n("Canvas Input"));
2096     page->setObjectName("canvasinput");
2097     page->setIcon(KisIconUtils::loadIcon("config-canvas-input"));
2098     m_pages << page;
2099 
2100     // Display
2101     vbox = new KoVBox();
2102     page = new KPageWidgetItem(vbox, i18n("Display"));
2103     page->setObjectName("display");
2104     page->setHeader(i18n("Display"));
2105     page->setIcon(KisIconUtils::loadIcon("config-display"));
2106     m_pages << page;
2107     addPage(page);
2108     m_displaySettings = new DisplaySettingsTab(vbox);
2109 
2110     // Color
2111     vbox = new KoVBox();
2112     page = new KPageWidgetItem(vbox, i18n("Color Management"));
2113     page->setObjectName("colormanagement");
2114     page->setHeader(i18nc("Label of color as in Color Management", "Color"));
2115     page->setIcon(KisIconUtils::loadIcon("config-color-manage"));
2116     m_pages << page;
2117     addPage(page);
2118     m_colorSettings = new ColorSettingsTab(vbox);
2119 
2120     // Performance
2121     vbox = new KoVBox();
2122     page = new KPageWidgetItem(vbox, i18n("Performance"));
2123     page->setObjectName("performance");
2124     page->setHeader(i18n("Performance"));
2125     page->setIcon(KisIconUtils::loadIcon("config-performance"));
2126     m_pages << page;
2127     addPage(page);
2128     m_performanceSettings = new PerformanceTab(vbox);
2129 
2130     // Tablet
2131     vbox = new KoVBox();
2132     page = new KPageWidgetItem(vbox, i18n("Tablet settings"));
2133     page->setObjectName("tablet");
2134     page->setHeader(i18n("Tablet"));
2135     page->setIcon(KisIconUtils::loadIcon("config-tablet"));
2136     m_pages << page;
2137     addPage(page);
2138     m_tabletSettings = new TabletSettingsTab(vbox);
2139 
2140     // full-screen mode
2141     vbox = new KoVBox();
2142     page = new KPageWidgetItem(vbox, i18n("Canvas-only settings"));
2143     page->setObjectName("canvasonly");
2144     page->setHeader(i18n("Canvas-only"));
2145     page->setIcon(KisIconUtils::loadIcon("config-canvas-only"));
2146     m_pages << page;
2147     addPage(page);
2148     m_fullscreenSettings = new FullscreenSettingsTab(vbox);
2149 
2150     // Pop-up Palette
2151     vbox = new KoVBox();
2152     page = new KPageWidgetItem(vbox, i18n("Pop-up Palette"));
2153     page->setObjectName("popuppalette");
2154     page->setHeader(i18n("Pop-up Palette"));
2155     page->setIcon(KisIconUtils::loadIcon("config-popup-palette"));
2156     m_pages << page;
2157     addPage(page);
2158     m_popupPaletteSettings = new PopupPaletteTab(vbox);
2159 
2160     // Author profiles
2161     m_authorPage = new KoConfigAuthorPage();
2162     page = addPage(m_authorPage, i18nc("@title:tab Author page", "Author" ));
2163     page->setObjectName("author");
2164     page->setHeader(i18n("Author"));
2165     page->setIcon(KisIconUtils::loadIcon("user-identity"));
2166     m_pages << page;
2167 
2168     KGuiItem::assign(button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
2169     KGuiItem::assign(button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
2170     QPushButton *restoreDefaultsButton = button(QDialogButtonBox::RestoreDefaults);
2171     restoreDefaultsButton->setText(i18nc("@action:button", "Restore Defaults"));
2172 
2173     connect(this, SIGNAL(accepted()), m_inputConfiguration, SLOT(saveChanges()));
2174     connect(this, SIGNAL(rejected()), m_inputConfiguration, SLOT(revertChanges()));
2175 
2176     KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance();
2177     QStringList keys = preferenceSetRegistry->keys();
2178     keys.sort();
2179     Q_FOREACH(const QString &key, keys) {
2180         KisAbstractPreferenceSetFactory *preferenceSetFactory = preferenceSetRegistry->value(key);
2181         KisPreferenceSet* preferenceSet = preferenceSetFactory->createPreferenceSet();
2182         vbox = new KoVBox();
2183         page = new KPageWidgetItem(vbox, preferenceSet->name());
2184         page->setHeader(preferenceSet->header());
2185         page->setIcon(preferenceSet->icon());
2186         addPage(page);
2187         preferenceSet->setParent(vbox);
2188         preferenceSet->loadPreferences();
2189 
2190         connect(restoreDefaultsButton, SIGNAL(clicked(bool)), preferenceSet, SLOT(loadDefaultPreferences()), Qt::UniqueConnection);
2191         connect(this, SIGNAL(accepted()), preferenceSet, SLOT(savePreferences()), Qt::UniqueConnection);
2192     }
2193 
2194     connect(restoreDefaultsButton, SIGNAL(clicked(bool)), this, SLOT(slotDefault()));
2195 
2196     KisConfig cfg(true);
2197     QString currentPageName = cfg.readEntry<QString>("KisDlgPreferences/CurrentPage");
2198     Q_FOREACH(KPageWidgetItem *page, m_pages) {
2199         if (page->objectName() == currentPageName) {
2200             setCurrentPage(page);
2201             break;
2202         }
2203     }
2204 
2205     {
2206         // HACK ALERT! Remove title widget background, thus making
2207         // it consistent across all systems
2208         const auto *titleWidget = findChild<KTitleWidget*>();
2209         if (titleWidget) {
2210             QLayoutItem *titleFrame = titleWidget->layout()->itemAt(0); // vboxLayout -> titleFrame
2211             if (titleFrame) {
2212                 titleFrame->widget()->setBackgroundRole(QPalette::Window);
2213             }
2214         }
2215     }
2216 }
2217 
2218 KisDlgPreferences::~KisDlgPreferences()
2219 {
2220     KisConfig cfg(true);
2221     cfg.writeEntry<QString>("KisDlgPreferences/CurrentPage", currentPage()->objectName());
2222 }
2223 
2224 void KisDlgPreferences::showEvent(QShowEvent *event){
2225     KPageDialog::showEvent(event);
2226     button(QDialogButtonBox::Cancel)->setAutoDefault(false);
2227     button(QDialogButtonBox::Ok)->setAutoDefault(false);
2228     button(QDialogButtonBox::RestoreDefaults)->setAutoDefault(false);
2229     button(QDialogButtonBox::Cancel)->setDefault(false);
2230     button(QDialogButtonBox::Ok)->setDefault(false);
2231     button(QDialogButtonBox::RestoreDefaults)->setDefault(false);
2232 }
2233 
2234 void KisDlgPreferences::slotButtonClicked(QAbstractButton *button)
2235 {
2236     if (buttonBox()->buttonRole(button) == QDialogButtonBox::RejectRole) {
2237         m_cancelClicked = true;
2238     }
2239 }
2240 
2241 void KisDlgPreferences::slotDefault()
2242 {
2243     if (currentPage()->objectName() == "general") {
2244         m_general->setDefault();
2245     }
2246     else if (currentPage()->objectName() == "shortcuts") {
2247         m_shortcutSettings->setDefault();
2248     }
2249     else if (currentPage()->objectName() == "display") {
2250         m_displaySettings->setDefault();
2251     }
2252     else if (currentPage()->objectName() == "colormanagement") {
2253         m_colorSettings->setDefault();
2254     }
2255     else if (currentPage()->objectName() == "performance") {
2256         m_performanceSettings->load(true);
2257     }
2258     else if (currentPage()->objectName() == "tablet") {
2259         m_tabletSettings->setDefault();
2260     }
2261     else if (currentPage()->objectName() == "canvasonly") {
2262         m_fullscreenSettings->setDefault();
2263     }
2264     else if (currentPage()->objectName() == "canvasinput") {
2265         m_inputConfiguration->setDefaults();
2266     }
2267     else if (currentPage()->objectName() == "popuppalette") {
2268         m_popupPaletteSettings->setDefault();
2269     }
2270 }
2271 
2272 bool KisDlgPreferences::editPreferences()
2273 {
2274     connect(this->buttonBox(), SIGNAL(clicked(QAbstractButton*)), this, SLOT(slotButtonClicked(QAbstractButton*)));
2275 
2276     int retval = exec();
2277     Q_UNUSED(retval);
2278 
2279     if (!m_cancelClicked) {
2280         // General settings
2281         KisConfig cfg(false);
2282         KisImageConfig cfgImage(false);
2283 
2284         cfg.setNewCursorStyle(m_general->cursorStyle());
2285         cfg.setNewOutlineStyle(m_general->outlineStyle());
2286         cfg.setSeparateEraserCursor(m_general->m_chkSeparateEraserCursor->isChecked());
2287         cfg.setEraserCursorStyle(m_general->eraserCursorStyle());
2288         cfg.setEraserOutlineStyle(m_general->eraserOutlineStyle());
2289         cfg.setShowRootLayer(m_general->showRootLayer());
2290         cfg.setShowOutlineWhilePainting(m_general->showOutlineWhilePainting());
2291         cfg.setForceAlwaysFullSizedOutline(!m_general->m_changeBrushOutline->isChecked());
2292         cfg.setShowEraserOutlineWhilePainting(m_general->showEraserOutlineWhilePainting());
2293         cfg.setForceAlwaysFullSizedEraserOutline(!m_general->m_changeEraserBrushOutline->isChecked());
2294         cfg.setSessionOnStartup(m_general->sessionOnStartup());
2295         cfg.setSaveSessionOnQuit(m_general->saveSessionOnQuit());
2296 
2297         KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs");
2298         group.writeEntry("DontUseNativeFileDialog", !m_general->m_chkNativeFileDialog->isChecked());
2299 
2300         cfgImage.setMaxBrushSize(m_general->intMaxBrushSize->value());
2301 
2302         cfg.writeEntry<bool>("use_custom_system_font", m_general->chkUseCustomFont->isChecked());
2303         if (m_general->chkUseCustomFont->isChecked()) {
2304             cfg.writeEntry<QString>("custom_system_font", m_general->cmbCustomFont->currentFont().family());
2305             cfg.writeEntry<int>("custom_font_size", m_general->intFontSize->value());
2306         }
2307         else {
2308             cfg.writeEntry<QString>("custom_system_font", "");
2309             cfg.writeEntry<int>("custom_font_size", -1);
2310         }
2311 
2312         cfg.writeEntry<int>("mdi_viewmode", m_general->mdiMode());
2313         cfg.setMDIBackgroundColor(m_general->m_mdiColor->color().toXML());
2314         cfg.setMDIBackgroundImage(m_general->m_backgroundimage->text());
2315         cfg.writeEntry<int>("mdi_rubberband", m_general->m_chkRubberBand->isChecked());
2316         cfg.setAutoSaveInterval(m_general->autoSaveInterval());
2317         cfg.writeEntry("autosavefileshidden", m_general->chkHideAutosaveFiles->isChecked());
2318 
2319         cfg.setBackupFile(m_general->m_backupFileCheckBox->isChecked());
2320         cfg.writeEntry("backupfilelocation", m_general->cmbBackupFileLocation->currentIndex());
2321         cfg.writeEntry("backupfilesuffix", m_general->txtBackupFileSuffix->text());
2322         cfg.writeEntry("numberofbackupfiles", m_general->intNumBackupFiles->value());
2323 
2324 
2325         cfg.setShowCanvasMessages(m_general->showCanvasMessages());
2326         cfg.setCompressKra(m_general->compressKra());
2327         cfg.setTrimKra(m_general->trimKra());
2328         cfg.setTrimFramesImport(m_general->trimFramesImport());
2329         cfg.setUseZip64(m_general->useZip64());
2330         cfg.setPasteFormat(m_general->m_pasteFormatGroup.checkedId());
2331 
2332         const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
2333         QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
2334         kritarc.setValue("EnableHiDPI", m_general->m_chkHiDPI->isChecked());
2335 #ifdef HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY
2336         kritarc.setValue("EnableHiDPIFractionalScaling", m_general->m_chkHiDPIFractionalScaling->isChecked());
2337 #endif
2338         kritarc.setValue("LogUsage", m_general->chkUsageLogging->isChecked());
2339 
2340         cfg.setToolOptionsInDocker(m_general->toolOptionsInDocker());
2341 
2342         cfg.writeEntry<bool>("useCreamyAlphaDarken", (bool)!m_general->cmbFlowMode->currentIndex());
2343         cfg.writeEntry<bool>("useSubtractiveBlendingForCmykColorSpaces", (bool)!m_general->cmbCmykBlendingMode->currentIndex());
2344 
2345         cfg.setZoomSteps(m_general->zoomSteps());
2346         cfg.setKineticScrollingEnabled(m_general->kineticScrollingEnabled());
2347         cfg.setKineticScrollingGesture(m_general->kineticScrollingGesture());
2348         cfg.setKineticScrollingSensitivity(m_general->kineticScrollingSensitivity());
2349         cfg.setKineticScrollingHideScrollbars(m_general->kineticScrollingHiddenScrollbars());
2350 
2351         cfg.setZoomMarginSize(m_general->zoomMarginSize());
2352 
2353         cfg.setSwitchSelectionCtrlAlt(m_general->switchSelectionCtrlAlt());
2354         cfg.setDisableTouchOnCanvas(!m_general->chkEnableTouch->isChecked());
2355         cfg.setActivateTransformToolAfterPaste(m_general->chkEnableTransformToolAfterPaste->isChecked());
2356         cfg.setZoomHorizontal(m_general->chkZoomHorizontally->isChecked());
2357         cfg.setConvertToImageColorspaceOnImport(m_general->convertToImageColorspaceOnImport());
2358         cfg.setUndoStackLimit(m_general->undoStackSize());
2359         cfg.setCumulativeUndoRedo(m_general->chkCumulativeUndo->isChecked());
2360         cfg.setCumulativeUndoData(m_general->m_cumulativeUndoData);
2361 
2362         cfg.setAutoPinLayersToTimeline(m_general->autopinLayersToTimeline());
2363         cfg.setAdaptivePlaybackRange(m_general->adaptivePlaybackRange());
2364 
2365 #ifdef Q_OS_ANDROID
2366         QFileInfo fi(m_general->m_resourceFolderSelector->currentData(Qt::UserRole).value<QString>());
2367 #else
2368         QFileInfo fi(m_general->m_urlResourceFolder->fileName());
2369 #endif
2370         if (fi.isWritable()) {
2371             cfg.writeEntry(KisResourceLocator::resourceLocationKey, fi.filePath());
2372         }
2373 
2374         KisImageConfig(true).setRenameMergedLayers(m_general->renameMergedLayers());
2375         cfg.setRenamePastedLayers(m_general->renamePastedLayers());
2376 
2377         // Color settings
2378         cfg.setUseSystemMonitorProfile(m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked());
2379         for (int i = 0; i < QApplication::screens().count(); ++i) {
2380             if (m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()) {
2381                 int currentIndex = m_colorSettings->m_monitorProfileWidgets[i]->currentIndex();
2382                 QString monitorid = m_colorSettings->m_monitorProfileWidgets[i]->itemData(currentIndex).toString();
2383                 cfg.setMonitorForScreen(i, monitorid);
2384             }
2385             else {
2386                 cfg.setMonitorProfile(i,
2387                                       m_colorSettings->m_monitorProfileWidgets[i]->currentUnsqueezedText(),
2388                                       m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked());
2389             }
2390         }
2391         cfg.setUseDefaultColorSpace(m_colorSettings->m_page->useDefColorSpace->isChecked());
2392         if (cfg.useDefaultColorSpace())
2393         {
2394             KoID currentWorkingColorSpace = m_colorSettings->m_page->cmbWorkingColorSpace->currentItem();
2395             cfg.setWorkingColorSpace(currentWorkingColorSpace.id());
2396             cfg.defColorModel(KoColorSpaceRegistry::instance()->colorSpaceColorModelId(currentWorkingColorSpace.id()).id());
2397             cfg.setDefaultColorDepth(KoColorSpaceRegistry::instance()->colorSpaceColorDepthId(currentWorkingColorSpace.id()).id());
2398         }
2399 
2400         cfgImage.setDefaultProofingConfig(m_colorSettings->m_page->proofingSpaceSelector->currentColorSpace(),
2401                                           m_colorSettings->m_page->cmbProofingIntent->currentIndex(),
2402                                           m_colorSettings->m_page->ckbProofBlackPoint->isChecked(),
2403                                           m_colorSettings->m_page->gamutAlarm->color(),
2404                                           (double)m_colorSettings->m_page->sldAdaptationState->value()/20);
2405         cfg.setUseBlackPointCompensation(m_colorSettings->m_page->chkBlackpoint->isChecked());
2406         cfg.setAllowLCMSOptimization(m_colorSettings->m_page->chkAllowLCMSOptimization->isChecked());
2407         cfg.setForcePaletteColors(m_colorSettings->m_page->chkForcePaletteColor->isChecked());
2408         cfg.setPasteBehaviour(m_colorSettings->m_pasteBehaviourGroup.checkedId());
2409         cfg.setRenderIntent(m_colorSettings->m_page->cmbMonitorIntent->currentIndex());
2410 
2411         // Tablet settings
2412         cfg.setPressureTabletCurve( m_tabletSettings->m_page->pressureCurve->curve().toString() );
2413         cfg.setUseRightMiddleTabletButtonWorkaround(
2414             m_tabletSettings->m_page->chkUseRightMiddleClickWorkaround->isChecked());
2415 
2416 #if defined Q_OS_WIN && (!defined USE_QT_TABLET_WINDOWS || defined QT_HAS_WINTAB_SWITCH)
2417 #ifdef USE_QT_TABLET_WINDOWS
2418         // ask Qt if WinInk is actually available
2419         const bool isWinInkAvailable = true;
2420 #else
2421         const bool isWinInkAvailable = KisTabletSupportWin8::isAvailable();
2422 #endif
2423         if (isWinInkAvailable) {
2424             cfg.setUseWin8PointerInput(m_tabletSettings->m_page->radioWin8PointerInput->isChecked());
2425         }
2426 #endif
2427         cfg.writeEntry<bool>("useTimestampsForBrushSpeed", m_tabletSettings->m_page->chkUseTimestampsForBrushSpeed->isChecked());
2428         cfg.writeEntry<int>("maxAllowedSpeedValue", m_tabletSettings->m_page->intMaxAllowedBrushSpeed->value());
2429         cfg.writeEntry<int>("speedValueSmoothing", m_tabletSettings->m_page->intBrushSpeedSmoothing->value());
2430 
2431         m_performanceSettings->save();
2432 
2433         if (!cfg.useOpenGL() && m_displaySettings->grpOpenGL->isChecked())
2434             cfg.setCanvasState("TRY_OPENGL");
2435 
2436         if (m_displaySettings->grpOpenGL->isChecked()) {
2437             KisOpenGL::OpenGLRenderer renderer = static_cast<KisOpenGL::OpenGLRenderer>(
2438                     m_displaySettings->cmbPreferredRenderer->itemData(
2439                             m_displaySettings->cmbPreferredRenderer->currentIndex()).toInt());
2440             KisOpenGL::setUserPreferredOpenGLRendererConfig(renderer);
2441         } else {
2442             KisOpenGL::setUserPreferredOpenGLRendererConfig(KisOpenGL::RendererNone);
2443         }
2444 
2445         cfg.setUseOpenGLTextureBuffer(m_displaySettings->chkUseTextureBuffer->isChecked());
2446         cfg.setOpenGLFilteringMode(m_displaySettings->cmbFilterMode->currentIndex());
2447         cfg.setRootSurfaceFormat(&kritarc, indexToFormat(m_displaySettings->cmbPreferedRootSurfaceFormat->currentIndex()));
2448         cfg.setAssistantsDrawMode(indexToAssistantDrawMode(m_displaySettings->cmbAssistantsDrawMode->currentIndex()));
2449 
2450         cfg.setCheckSize(m_displaySettings->intCheckSize->value());
2451         cfg.setScrollingCheckers(m_displaySettings->chkMoving->isChecked());
2452         cfg.setCheckersColor1(m_displaySettings->colorChecks1->color().toQColor());
2453         cfg.setCheckersColor2(m_displaySettings->colorChecks2->color().toQColor());
2454         cfg.setCanvasBorderColor(m_displaySettings->canvasBorder->color().toQColor());
2455         cfg.setHideScrollbars(m_displaySettings->hideScrollbars->isChecked());
2456         KoColor c = m_displaySettings->btnSelectionOverlayColor->color();
2457         c.setOpacity(m_displaySettings->sldSelectionOverlayOpacity->value());
2458         cfgImage.setSelectionOverlayMaskColor(c.toQColor());
2459         cfgImage.setSelectionOutlineOpacity(m_displaySettings->sldSelectionOutlineOpacity->value());
2460         cfg.setAntialiasCurves(m_displaySettings->chkCurveAntialiasing->isChecked());
2461         cfg.setAntialiasSelectionOutline(m_displaySettings->chkSelectionOutlineAntialiasing->isChecked());
2462         cfg.setShowSingleChannelAsColor(m_displaySettings->chkChannelsAsColor->isChecked());
2463         cfg.setHidePopups(m_displaySettings->chkHidePopups->isChecked());
2464 
2465         cfg.setHideDockersFullscreen(m_fullscreenSettings->chkDockers->checkState());
2466         cfg.setHideMenuFullscreen(m_fullscreenSettings->chkMenu->checkState());
2467         cfg.setHideScrollbarsFullscreen(m_fullscreenSettings->chkScrollbars->checkState());
2468         cfg.setHideStatusbarFullscreen(m_fullscreenSettings->chkStatusbar->checkState());
2469         cfg.setHideTitlebarFullscreen(m_fullscreenSettings->chkTitlebar->checkState());
2470         cfg.setHideToolbarFullscreen(m_fullscreenSettings->chkToolbar->checkState());
2471 
2472         cfg.setCursorMainColor(m_general->cursorColorButton->color().toQColor());
2473         cfg.setEraserCursorMainColor(m_general->eraserCursorColorButton->color().toQColor());
2474         cfg.setPixelGridColor(m_displaySettings->pixelGridColorButton->color().toQColor());
2475         cfg.setPixelGridDrawingThreshold(m_displaySettings->pixelGridDrawingThresholdBox->value() / 100);
2476 
2477         m_popupPaletteSettings->save();
2478         m_authorPage->apply();
2479 
2480         cfg.logImportantSettings();
2481         cfg.writeEntry("forcedDpiForQtFontBugWorkaround", m_general->forcedFontDpi());
2482     }
2483 
2484     return !m_cancelClicked;
2485 }