File indexing completed on 2025-03-09 03:59:01

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2004-08-03
0007  * Description : setup Image Editor interface.
0008  *
0009  * SPDX-FileCopyrightText: 2004-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "setupeditoriface.h"
0016 
0017 // Qt includes
0018 
0019 #include <QCheckBox>
0020 #include <QColor>
0021 #include <QGroupBox>
0022 #include <QLabel>
0023 #include <QVBoxLayout>
0024 #include <QPainter>
0025 #include <QApplication>
0026 #include <QStyle>
0027 #include <QStandardPaths>
0028 
0029 // KDE includes
0030 
0031 #include <kconfiggroup.h>
0032 #include <ksharedconfig.h>
0033 #include <klocalizedstring.h>
0034 
0035 // Local includes
0036 
0037 #include "dlayoutbox.h"
0038 #include "dnuminput.h"
0039 #include "dimg.h"
0040 #include "histogramwidget.h"
0041 #include "exposurecontainer.h"
0042 #include "fullscreensettings.h"
0043 #include "dxmlguiwindow.h"
0044 #include "dcolorselector.h"
0045 
0046 namespace Digikam
0047 {
0048 
0049 class Q_DECL_HIDDEN SetupEditorIface::Private
0050 {
0051 public:
0052 
0053     explicit Private()
0054       : themebackgroundColor(nullptr),
0055         expoIndicatorMode   (nullptr),
0056         restoreSettings     (nullptr),
0057         expoPreview         (nullptr),
0058         colorBox            (nullptr),
0059         backgroundColor     (nullptr),
0060         underExposureColor  (nullptr),
0061         overExposureColor   (nullptr),
0062         expoPreviewHisto    (nullptr),
0063         fullScreenSettings  (nullptr),
0064         underExposurePcents (nullptr),
0065         overExposurePcents  (nullptr)
0066     {
0067     }
0068 
0069     static const QString  configGroupName;
0070     static const QString  configUseThemeBackgroundColorEntry;
0071     static const QString  configBackgroundColorEntry;
0072     static const QString  configUnderExposureColorEntry;
0073     static const QString  configOverExposureColorEntry;
0074     static const QString  configUnderExposurePercentsEntry;
0075     static const QString  configOverExposurePercentsEntry;
0076     static const QString  configExpoIndicatorModeEntry;
0077     static const QString  configRestoreSettingsEntry;
0078 
0079     QCheckBox*            themebackgroundColor;
0080     QCheckBox*            expoIndicatorMode;
0081     QCheckBox*            restoreSettings;
0082 
0083     QLabel*               expoPreview;
0084 
0085     DHBox*                colorBox;
0086     DColorSelector*       backgroundColor;
0087     DColorSelector*       underExposureColor;
0088     DColorSelector*       overExposureColor;
0089 
0090     HistogramWidget*      expoPreviewHisto;
0091 
0092     FullScreenSettings*   fullScreenSettings;
0093 
0094     DImg                  preview;
0095 
0096     DDoubleNumInput*      underExposurePcents;
0097     DDoubleNumInput*      overExposurePcents;
0098 };
0099 
0100 const QString SetupEditorIface::Private::configGroupName(QLatin1String("ImageViewer Settings"));
0101 const QString SetupEditorIface::Private::configUseThemeBackgroundColorEntry(QLatin1String("UseThemeBackgroundColor"));
0102 const QString SetupEditorIface::Private::configBackgroundColorEntry(QLatin1String("BackgroundColor"));
0103 const QString SetupEditorIface::Private::configUnderExposureColorEntry(QLatin1String("UnderExposureColor"));
0104 const QString SetupEditorIface::Private::configOverExposureColorEntry(QLatin1String("OverExposureColor"));
0105 const QString SetupEditorIface::Private::configUnderExposurePercentsEntry(QLatin1String("UnderExposurePercentsEntry"));
0106 const QString SetupEditorIface::Private::configOverExposurePercentsEntry(QLatin1String("OverExposurePercentsEntry"));
0107 const QString SetupEditorIface::Private::configExpoIndicatorModeEntry(QLatin1String("ExpoIndicatorMode"));
0108 const QString SetupEditorIface::Private::configRestoreSettingsEntry(QLatin1String("RestoreToolSettings"));
0109 
0110 // --------------------------------------------------------
0111 
0112 SetupEditorIface::SetupEditorIface(QWidget* const parent)
0113     : QScrollArea(parent),
0114       d          (new Private)
0115 {
0116     const int spacing    = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0117                              QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0118     QWidget* const panel = new QWidget(viewport());
0119     setWidget(panel);
0120     setWidgetResizable(true);
0121 
0122     QVBoxLayout* const layout = new QVBoxLayout(panel);
0123 
0124     // --------------------------------------------------------
0125 
0126     QGroupBox* const interfaceOptionsGroup = new QGroupBox(i18n("Interface Options"), panel);
0127     QVBoxLayout* const gLayout1            = new QVBoxLayout(interfaceOptionsGroup);
0128 
0129     d->themebackgroundColor                = new QCheckBox(i18n("&Use theme background color"),
0130                                                            interfaceOptionsGroup);
0131 
0132     d->themebackgroundColor->setWhatsThis(i18n("Enable this option to use the background theme "
0133                                                "color in the image editor area."));
0134 
0135     d->colorBox                        = new DHBox(interfaceOptionsGroup);
0136     QLabel* const backgroundColorlabel = new QLabel(i18n("&Background color:"), d->colorBox);
0137     d->backgroundColor                 = new DColorSelector(d->colorBox);
0138     backgroundColorlabel->setBuddy(d->backgroundColor);
0139     d->backgroundColor->setWhatsThis(i18n("Customize the background color to use "
0140                                           "in the image editor area."));
0141 
0142     gLayout1->addWidget(d->themebackgroundColor);
0143     gLayout1->addWidget(d->colorBox);
0144     gLayout1->setContentsMargins(spacing, spacing, spacing, spacing);
0145     gLayout1->setSpacing(spacing);
0146 
0147     // --------------------------------------------------------
0148 
0149     d->fullScreenSettings = new FullScreenSettings(FS_EDITOR, panel);
0150 
0151     // --------------------------------------------------------
0152 
0153     QGroupBox* const exposureOptionsGroup = new QGroupBox(i18n("Exposure Indicators"), panel);
0154     QGridLayout* const gLayout2           = new QGridLayout(exposureOptionsGroup);
0155 
0156     QLabel* const underExpoColorlabel     = new QLabel(i18n("&Under-exposure color: "), exposureOptionsGroup);
0157     d->underExposureColor                 = new DColorSelector(exposureOptionsGroup);
0158     underExpoColorlabel->setBuddy(d->underExposureColor);
0159     d->underExposureColor->setWhatsThis(i18n("Customize color used in image editor to identify "
0160                                              "under-exposed pixels."));
0161 
0162     QLabel* const underExpoPcentlabel = new QLabel(i18n("Under-exposure percents: "), exposureOptionsGroup);
0163     d->underExposurePcents            = new DDoubleNumInput(exposureOptionsGroup);
0164     d->underExposurePcents->setDecimals(1);
0165     d->underExposurePcents->setRange(0.1, 5.0, 0.1);
0166     d->underExposurePcents->setDefaultValue(1.0);
0167     underExpoPcentlabel->setBuddy(d->underExposurePcents);
0168     d->underExposurePcents->setWhatsThis(i18n("Adjust the percents of the bottom of image histogram "
0169                                               "which will be used to check under exposed pixels."));
0170 
0171     QLabel* const overExpoColorlabel = new QLabel(i18n("&Over-exposure color: "), exposureOptionsGroup);
0172     d->overExposureColor             = new DColorSelector(exposureOptionsGroup);
0173     overExpoColorlabel->setBuddy(d->overExposureColor);
0174     d->overExposureColor->setWhatsThis(i18n("Customize color used in image editor to identify "
0175                                             "over-exposed pixels."));
0176 
0177     QLabel* const overExpoPcentlabel = new QLabel(i18n("Over-exposure percents: "), exposureOptionsGroup);
0178     d->overExposurePcents            = new DDoubleNumInput(exposureOptionsGroup);
0179     d->overExposurePcents->setDecimals(1);
0180     d->overExposurePcents->setRange(0.1, 5.0, 0.1);
0181     d->overExposurePcents->setDefaultValue(1.0);
0182     overExpoPcentlabel->setBuddy(d->underExposurePcents);
0183     d->overExposurePcents->setWhatsThis(i18n("Adjust the percents of the top of image histogram "
0184                                              "which will be used to check over exposed pixels."));
0185 
0186     d->expoIndicatorMode = new QCheckBox(i18n("Indicate exposure as pure color"), exposureOptionsGroup);
0187     d->expoIndicatorMode->setWhatsThis(i18n("If this option is enabled, over- and under-exposure indicators will be displayed "
0188                                             "only when pure white and pure black color matches, as all color components match "
0189                                             "the condition in the same time. "
0190                                             "Otherwise, indicators are turned on when one of the color components matches the condition."));
0191 
0192     QLabel* const exampleLabel = new QLabel(i18n("Example:"), exposureOptionsGroup);
0193     d->expoPreview             = new QLabel(exposureOptionsGroup);
0194     d->expoPreviewHisto        = new HistogramWidget(256, 128, exposureOptionsGroup, false, false);
0195     QImage image(QStandardPaths::locate(QStandardPaths::GenericDataLocation,
0196                                         QLatin1String("digikam/data/sample-aix.png")));
0197     d->preview                 = DImg(image);
0198 
0199     if (!d->preview.isNull())
0200     {
0201         d->expoPreviewHisto->updateData(d->preview);
0202     }
0203 
0204     d->expoPreviewHisto->setChannelType(ColorChannels);
0205     d->expoPreview->setFrameStyle(QFrame::Box | QFrame::Plain);
0206 
0207     gLayout2->addWidget(underExpoColorlabel,    0, 0, 1, 2);
0208     gLayout2->addWidget(d->underExposureColor,  0, 2, 1, 1);
0209     gLayout2->addWidget(underExpoPcentlabel,    1, 0, 1, 2);
0210     gLayout2->addWidget(d->underExposurePcents, 1, 2, 1, 1);
0211     gLayout2->addWidget(overExpoColorlabel,     2, 0, 1, 2);
0212     gLayout2->addWidget(d->overExposureColor,   2, 2, 1, 1);
0213     gLayout2->addWidget(overExpoPcentlabel,     3, 0, 1, 2);
0214     gLayout2->addWidget(d->overExposurePcents,  3, 2, 1, 1);
0215     gLayout2->addWidget(d->expoIndicatorMode,   4, 0, 1, 2);
0216     gLayout2->addWidget(exampleLabel,           5, 0, 1, 2);
0217     gLayout2->addWidget(d->expoPreview,         6, 0, 1, 1);
0218     gLayout2->addWidget(d->expoPreviewHisto,    6, 2, 1, 1);
0219     gLayout2->setColumnStretch(1, 10);
0220     gLayout2->setSpacing(spacing);
0221     gLayout2->setContentsMargins(spacing, spacing, spacing, spacing);
0222 
0223     // --------------------------------------------------------
0224 
0225     QGroupBox* const restoreSettingsGroup = new QGroupBox(i18n("Tool Options"), panel);
0226     QVBoxLayout* const gLayout3           = new QVBoxLayout(restoreSettingsGroup);
0227 
0228     d->restoreSettings                    = new QCheckBox(i18n("&Restore the settings of the Image Editor tools"),
0229                                                           restoreSettingsGroup);
0230     d->restoreSettings->setWhatsThis(i18n("Enable this option to restore the settings of the Image "
0231                                           "Editor tools from the last session. Otherwise, the "
0232                                           "default settings will be used."));
0233 
0234     gLayout3->addWidget(d->restoreSettings);
0235     gLayout3->setContentsMargins(spacing, spacing, spacing, spacing);
0236     gLayout3->setSpacing(spacing);
0237 
0238     // --------------------------------------------------------
0239 
0240     layout->addWidget(interfaceOptionsGroup);
0241     layout->addWidget(d->fullScreenSettings);
0242     layout->addWidget(exposureOptionsGroup);
0243     layout->addWidget(restoreSettingsGroup);
0244     layout->addStretch();
0245     layout->setContentsMargins(spacing, spacing, spacing, spacing);
0246     layout->setSpacing(spacing);
0247 
0248     // --------------------------------------------------------
0249 
0250     connect(d->themebackgroundColor, SIGNAL(toggled(bool)),
0251             this, SLOT(slotThemeBackgroundColor(bool)));
0252 
0253     connect(d->expoIndicatorMode, SIGNAL(toggled(bool)),
0254             this, SLOT(slotExpoSettingsChanged()));
0255 
0256     connect(d->underExposureColor, SIGNAL(signalColorSelected(QColor)),
0257             this, SLOT(slotExpoSettingsChanged()));
0258 
0259     connect(d->overExposureColor, SIGNAL(signalColorSelected(QColor)),
0260             this, SLOT(slotExpoSettingsChanged()));
0261 
0262     connect(d->underExposurePcents, SIGNAL(valueChanged(double)),
0263             this, SLOT(slotExpoSettingsChanged()));
0264 
0265     connect(d->underExposurePcents, SIGNAL(valueChanged(double)),
0266             this, SLOT(slotShowUnderExpoHistogramGuide(double)));
0267 
0268     connect(d->overExposurePcents, SIGNAL(valueChanged(double)),
0269             this, SLOT(slotExpoSettingsChanged()));
0270 
0271     connect(d->overExposurePcents, SIGNAL(valueChanged(double)),
0272             this, SLOT(slotShowOverExpoHistogramGuide(double)));
0273 
0274     readSettings();
0275 
0276     // --------------------------------------------------------
0277 
0278     slotExpoSettingsChanged();
0279 }
0280 
0281 SetupEditorIface::~SetupEditorIface()
0282 {
0283     delete d;
0284 }
0285 
0286 void SetupEditorIface::slotThemeBackgroundColor(bool e)
0287 {
0288     d->colorBox->setEnabled(!e);
0289 }
0290 
0291 void SetupEditorIface::slotExpoSettingsChanged()
0292 {
0293     ExposureSettingsContainer prm;
0294     prm.underExposureIndicator = true;
0295     prm.overExposureIndicator  = true;
0296     prm.exposureIndicatorMode  = d->expoIndicatorMode->isChecked();
0297     prm.underExposurePercent   = d->underExposurePcents->value();
0298     prm.overExposurePercent    = d->overExposurePcents->value();
0299     prm.underExposureColor     = d->underExposureColor->color();
0300     prm.overExposureColor      = d->overExposureColor->color();
0301 
0302     QPixmap pix                = d->preview.convertToPixmap();
0303     QPainter p(&pix);
0304     QImage pureColorMask       = d->preview.pureColorMask(&prm);
0305     QPixmap pixMask            = QPixmap::fromImage(pureColorMask);
0306     p.drawPixmap(0, 0, pixMask, 0, 0, pixMask.width(), pixMask.height());
0307 
0308     d->expoPreview->setPixmap(pix);
0309 }
0310 
0311 void SetupEditorIface::slotShowOverExpoHistogramGuide(double v)
0312 {
0313     int max  = lround(255.0 - (255.0 * v / 100.0));
0314     DColor color(max, max, max, max, false);
0315     d->expoPreviewHisto->setHistogramGuideByColor(color);
0316 }
0317 
0318 void SetupEditorIface::slotShowUnderExpoHistogramGuide(double v)
0319 {
0320     int min  = lround(0.0 + (255.0 * v / 100.0));
0321     DColor color(min, min, min, min, false);
0322     d->expoPreviewHisto->setHistogramGuideByColor(color);
0323 }
0324 
0325 void SetupEditorIface::readSettings()
0326 {
0327     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0328     KConfigGroup group        = config->group(d->configGroupName);
0329     QColor Black(Qt::black);
0330     QColor White(Qt::white);
0331     d->themebackgroundColor->setChecked(group.readEntry(d->configUseThemeBackgroundColorEntry, true));
0332     d->backgroundColor->setColor(group.readEntry(d->configBackgroundColorEntry,                Black));
0333     d->underExposureColor->setColor(group.readEntry(d->configUnderExposureColorEntry,          White));
0334     d->overExposureColor->setColor(group.readEntry(d->configOverExposureColorEntry,            Black));
0335     d->expoIndicatorMode->setChecked(group.readEntry(d->configExpoIndicatorModeEntry,          true));
0336     d->underExposurePcents->setValue(group.readEntry(d->configUnderExposurePercentsEntry,      1.0));
0337     d->overExposurePcents->setValue(group.readEntry(d->configOverExposurePercentsEntry,        1.0));
0338     d->restoreSettings->setChecked(group.readEntry(d->configRestoreSettingsEntry,              true));
0339     d->fullScreenSettings->readSettings(group);
0340 }
0341 
0342 void SetupEditorIface::applySettings()
0343 {
0344     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0345     KConfigGroup group        = config->group(d->configGroupName);
0346     group.writeEntry(d->configUseThemeBackgroundColorEntry, d->themebackgroundColor->isChecked());
0347     group.writeEntry(d->configBackgroundColorEntry,         d->backgroundColor->color());
0348     group.writeEntry(d->configUnderExposureColorEntry,      d->underExposureColor->color());
0349     group.writeEntry(d->configOverExposureColorEntry,       d->overExposureColor->color());
0350     group.writeEntry(d->configExpoIndicatorModeEntry,       d->expoIndicatorMode->isChecked());
0351     group.writeEntry(d->configUnderExposurePercentsEntry,   d->underExposurePcents->value());
0352     group.writeEntry(d->configOverExposurePercentsEntry,    d->overExposurePcents->value());
0353     group.writeEntry(d->configRestoreSettingsEntry,         d->restoreSettings->isChecked());
0354 
0355     d->fullScreenSettings->saveSettings(group);
0356 
0357     group.sync();
0358 }
0359 
0360 } // namespace Digikam
0361 
0362 #include "moc_setupeditoriface.cpp"