File indexing completed on 2025-01-05 03:56:18
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2013-08-19 0007 * Description : Image Quality settings widget 0008 * 0009 * SPDX-FileCopyrightText: 2013-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2013-2014 by Gowtham Ashok <gwty93 at gmail dot com> 0011 * SPDX-FileCopyrightText: 2021-2022 by Phuoc Khanh Le <phuockhanhnk94 at gmail dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "imagequalitysettings.h" 0018 0019 // Qt includes 0020 0021 #include <QCheckBox> 0022 #include <QRadioButton> 0023 #include <QButtonGroup> 0024 #include <QGroupBox> 0025 #include <QGridLayout> 0026 #include <QLabel> 0027 #include <QVBoxLayout> 0028 #include <QIcon> 0029 #include <QApplication> 0030 #include <QStyle> 0031 #include <QPushButton> 0032 0033 // KDE includes 0034 0035 #include <klocalizedstring.h> 0036 0037 // Local includes 0038 0039 #include "dlayoutbox.h" 0040 #include "picklabelwidget.h" 0041 #include "dnuminput.h" 0042 0043 namespace Digikam 0044 { 0045 0046 class Q_DECL_HIDDEN ImageQualitySettings::Private 0047 { 0048 public: 0049 0050 enum DetectMethod 0051 { 0052 AESTHETIC = 0, 0053 BASICFACTORS 0054 }; 0055 0056 public: 0057 0058 explicit Private() 0059 : detectBlur (nullptr), 0060 detectNoise (nullptr), 0061 detectCompression (nullptr), 0062 detectExposure (nullptr), 0063 detectButtonGroup (nullptr), 0064 detectAesthetic (nullptr), 0065 detectBasicFactors (nullptr), 0066 setRejected (nullptr), 0067 setPending (nullptr), 0068 setAccepted (nullptr), 0069 lbl2 (nullptr), 0070 lbl3 (nullptr), 0071 lbl4 (nullptr), 0072 lbl5 (nullptr), 0073 lbl6 (nullptr), 0074 lbl7 (nullptr), 0075 setRejectedThreshold(nullptr), 0076 setPendingThreshold (nullptr), 0077 setAcceptedThreshold(nullptr), 0078 setBlurWeight (nullptr), 0079 setNoiseWeight (nullptr), 0080 setCompressionWeight(nullptr) 0081 { 0082 } 0083 0084 QCheckBox* detectBlur; 0085 QCheckBox* detectNoise; 0086 QCheckBox* detectCompression; 0087 QCheckBox* detectExposure; 0088 0089 QButtonGroup* detectButtonGroup; 0090 QRadioButton* detectAesthetic; 0091 QRadioButton* detectBasicFactors; 0092 0093 QCheckBox* setRejected; 0094 QCheckBox* setPending; 0095 QCheckBox* setAccepted; 0096 0097 QLabel* lbl2; 0098 QLabel* lbl3; 0099 QLabel* lbl4; 0100 QLabel* lbl5; 0101 QLabel* lbl6; 0102 QLabel* lbl7; 0103 0104 DIntNumInput* setRejectedThreshold; 0105 DIntNumInput* setPendingThreshold; 0106 DIntNumInput* setAcceptedThreshold; 0107 DIntNumInput* setBlurWeight; 0108 DIntNumInput* setNoiseWeight; 0109 DIntNumInput* setCompressionWeight; 0110 }; 0111 0112 // -------------------------------------------------------- 0113 0114 ImageQualitySettings::ImageQualitySettings(QWidget* const parent) 0115 : QWidget(parent), 0116 d (new Private) 0117 { 0118 const int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0119 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)); 0120 0121 DHBox* const hlay1 = new DHBox(this); 0122 0123 d->setRejected = new QCheckBox(i18nc("@option:check", "Assign 'Rejected' Label to Low Quality Pictures"), hlay1); 0124 d->setRejected->setToolTip(i18nc("@info:tooltip", "Low quality images detected by blur, noise, and compression analysis will be assigned to Rejected label.")); 0125 0126 QWidget* const hspace1 = new QWidget(hlay1); 0127 hlay1->setStretchFactor(hspace1, 10); 0128 0129 QLabel* const workIcon1 = new QLabel(hlay1); 0130 workIcon1->setPixmap(QIcon::fromTheme(QLatin1String("flag-red")).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize))); 0131 0132 // ------------------------------------------------------------------------------ 0133 0134 DHBox* const hlay2 = new DHBox(this); 0135 0136 d->setPending = new QCheckBox(i18nc("@option:check", "Assign 'Pending' Label to Medium Quality Pictures"), hlay2); 0137 d->setPending->setToolTip(i18nc("@info:tooltip", "Medium quality images detected by blur, noise, and compression analysis will be assigned to Pending label.")); 0138 0139 QWidget* const hspace2 = new QWidget(hlay2); 0140 hlay2->setStretchFactor(hspace2, 10); 0141 0142 QLabel* const workIcon2 = new QLabel(hlay2); 0143 workIcon2->setPixmap(QIcon::fromTheme(QLatin1String("flag-yellow")).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize))); 0144 0145 // ------------------------------------------------------------------------------ 0146 0147 DHBox* const hlay3 = new DHBox(this); 0148 0149 d->setAccepted = new QCheckBox(i18nc("@option:check", "Assign 'Accepted' Label to High Quality Pictures"), hlay3); 0150 d->setAccepted->setToolTip(i18nc("@info:tooltip", "High quality images detected by blur, noise, and compression analysis will be assigned to Accepted label.")); 0151 0152 QWidget* const hspace3 = new QWidget(hlay3); 0153 hlay3->setStretchFactor(hspace3, 10); 0154 0155 QLabel* const workIcon3 = new QLabel(hlay3); 0156 workIcon3->setPixmap(QIcon::fromTheme(QLatin1String("flag-green")).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize))); 0157 0158 // ------------------------------------------------------------------------------ 0159 0160 d->detectButtonGroup = new QButtonGroup(this); 0161 d->detectButtonGroup->setExclusive(true); 0162 0163 d->detectAesthetic = new QRadioButton(i18nc("@option:radio", "Detect Aesthetic Image using Deep Learning"), 0164 this); 0165 d->detectAesthetic->setToolTip(i18nc("@info:tooltip", "Detect if the image has aesthetic value.\n" 0166 "The aesthetic detection engine use deep learning model to classify images")); 0167 0168 d->detectButtonGroup->addButton(d->detectAesthetic, Private::AESTHETIC); 0169 0170 d->detectBasicFactors = new QRadioButton(i18nc("@option:radio", "Detect Quality Using Basic Factors"), 0171 this); 0172 d->detectBasicFactors->setToolTip(i18nc("@info:tooltip", "Detect if the image is sabotaging by four basic factors " 0173 "(blur, noise, exposure, and compression).")); 0174 0175 d->detectButtonGroup->addButton(d->detectBasicFactors, Private::BASICFACTORS); 0176 d->detectAesthetic->setChecked(true); 0177 0178 // ------------------------------------------------------------------------------ 0179 0180 QWidget* const basicView = new QWidget(this); 0181 QGridLayout* const grid1 = new QGridLayout(basicView); 0182 0183 d->lbl2 = new QLabel(i18nc("@label", "Rejected threshold:"), basicView); 0184 d->lbl2->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0185 d->setRejectedThreshold = new DIntNumInput(basicView); 0186 d->setRejectedThreshold->setDefaultValue(10); 0187 d->setRejectedThreshold->setRange(1, 100, 1); 0188 d->setRejectedThreshold->setToolTip(i18nc("@info:tooltip", "Threshold below which all pictures are assigned Rejected Label")); 0189 0190 d->lbl3 = new QLabel(i18nc("@label", "Pending threshold:"), basicView); 0191 d->lbl3->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0192 d->setPendingThreshold = new DIntNumInput(basicView); 0193 d->setPendingThreshold->setDefaultValue(40); 0194 d->setPendingThreshold->setRange(1, 100, 1); 0195 d->setPendingThreshold->setToolTip(i18nc("@info:tooltip", "Threshold below which all pictures are assigned Pending Label")); 0196 0197 d->lbl4 = new QLabel(i18nc("@label", "Accepted threshold:"), basicView); 0198 d->lbl4->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0199 d->setAcceptedThreshold = new DIntNumInput(basicView); 0200 d->setAcceptedThreshold->setDefaultValue(60); 0201 d->setAcceptedThreshold->setRange(1, 100, 1); 0202 d->setAcceptedThreshold->setToolTip(i18nc("@info:tooltip", "Threshold above which all pictures are assigned Accepted Label")); 0203 0204 d->detectBlur = new QCheckBox(i18nc("@option:check", "Detect Blur"), basicView); 0205 d->detectBlur->setToolTip(i18nc("@info:tooltip", "Detect the amount of blur in the images passed to it")); 0206 0207 d->lbl5 = new QLabel(i18nc("@label", "Weight:"), basicView); 0208 d->lbl5->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0209 d->setBlurWeight = new DIntNumInput(basicView); 0210 d->setBlurWeight->setDefaultValue(100); 0211 d->setBlurWeight->setRange(1, 100, 1); 0212 d->setBlurWeight->setToolTip(i18nc("@info:tooltip", "Weight to assign to Blur Algorithm")); 0213 0214 d->detectNoise = new QCheckBox(i18nc("@option:check", "Detect Noise"), basicView); 0215 d->detectNoise->setToolTip(i18nc("@info:tooltip", "Detect the amount of noise in the images passed to it")); 0216 0217 d->lbl6 = new QLabel(i18nc("@label", "Weight:"), basicView); 0218 d->lbl6->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0219 d->setNoiseWeight = new DIntNumInput(basicView); 0220 d->setNoiseWeight->setDefaultValue(100); 0221 d->setNoiseWeight->setRange(1, 100, 1); 0222 d->setNoiseWeight->setToolTip(i18nc("@info:tooltip", "Weight to assign to Noise Algorithm")); 0223 0224 d->detectCompression = new QCheckBox(i18nc("@option:check", "Detect Compression"), basicView); 0225 d->detectCompression->setToolTip(i18nc("@info:tooltip", "Detect the amount of compression in the images passed to it")); 0226 0227 d->lbl7 = new QLabel(i18nc("@label", "Weight:"), basicView); 0228 d->lbl7->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0229 d->setCompressionWeight = new DIntNumInput(basicView); 0230 d->setCompressionWeight->setDefaultValue(100); 0231 d->setCompressionWeight->setRange(1, 100, 1); 0232 d->setCompressionWeight->setToolTip(i18nc("@info:tooltip", "Weight to assign to Compression Algorithm")); 0233 0234 d->detectExposure = new QCheckBox(i18nc("@option:check", "Detect Under and Over Exposure"), basicView); 0235 d->detectExposure->setToolTip(i18nc("@info:tooltip", "Detect if the images are under-exposed or over-exposed")); 0236 0237 grid1->addWidget(d->lbl2, 0, 0, 1, 2); 0238 grid1->addWidget(d->setRejectedThreshold, 0, 2, 1, 1); 0239 grid1->addWidget(d->lbl3, 1, 0, 1, 2); 0240 grid1->addWidget(d->setPendingThreshold, 1, 2, 1, 1); 0241 grid1->addWidget(d->lbl4, 2, 0, 1, 2); 0242 grid1->addWidget(d->setAcceptedThreshold, 2, 2, 1, 1); 0243 0244 grid1->addWidget(d->detectBlur, 3, 0, 1, 1); 0245 grid1->addWidget(d->lbl5, 3, 1, 1, 1); 0246 grid1->addWidget(d->setBlurWeight, 3, 2, 1, 1); 0247 0248 grid1->addWidget(d->detectNoise, 4, 0, 1, 1); 0249 grid1->addWidget(d->lbl6, 4, 1, 1, 1); 0250 grid1->addWidget(d->setNoiseWeight, 4, 2, 1, 1); 0251 0252 grid1->addWidget(d->detectCompression, 5, 0, 1, 1); 0253 grid1->addWidget(d->lbl7, 5, 1, 1, 1); 0254 grid1->addWidget(d->setCompressionWeight, 5, 2, 1, 1); 0255 0256 grid1->addWidget(d->detectExposure, 6, 0, 1, 3); 0257 grid1->setContentsMargins(2 * spacing, spacing, spacing, spacing); 0258 grid1->setColumnStretch(0, 1); 0259 grid1->setColumnStretch(1, 1); 0260 grid1->setColumnStretch(2, 100); 0261 grid1->setRowStretch(7, 10); 0262 0263 // ------------------------------------------------------------------------------ 0264 0265 QGridLayout* const glay = new QGridLayout(this); 0266 glay->addWidget(hlay1, 0, 1, 1, 1); 0267 glay->addWidget(hlay2, 1, 1, 1, 1); 0268 glay->addWidget(hlay3, 2, 1, 1, 1); 0269 glay->addWidget(d->detectAesthetic, 3, 1, 1, 1); 0270 glay->addWidget(d->detectBasicFactors, 4, 1, 1, 1); 0271 glay->addWidget(basicView, 5, 1, 1, 1); 0272 glay->setColumnStretch(1, 10); 0273 glay->setContentsMargins(2 * spacing, spacing, spacing, spacing); 0274 0275 // ------------------------------------------------------------------------------ 0276 0277 connect(d->detectBlur, SIGNAL(toggled(bool)), 0278 this, SIGNAL(signalSettingsChanged())); 0279 0280 connect(d->detectNoise, SIGNAL(toggled(bool)), 0281 this, SIGNAL(signalSettingsChanged())); 0282 0283 connect(d->detectCompression, SIGNAL(toggled(bool)), 0284 this, SIGNAL(signalSettingsChanged())); 0285 0286 connect(d->detectExposure, SIGNAL(toggled(bool)), 0287 this, SIGNAL(signalSettingsChanged())); 0288 0289 connect(d->setRejected, SIGNAL(toggled(bool)), 0290 this, SIGNAL(signalSettingsChanged())); 0291 0292 connect(d->setPending, SIGNAL(toggled(bool)), 0293 this, SIGNAL(signalSettingsChanged())); 0294 0295 connect(d->setAccepted, SIGNAL(toggled(bool)), 0296 this, SIGNAL(signalSettingsChanged())); 0297 0298 connect(d->setRejectedThreshold, SIGNAL(valueChanged(int)), 0299 this, SIGNAL(signalSettingsChanged())); 0300 0301 connect(d->setPendingThreshold, SIGNAL(valueChanged(int)), 0302 this, SIGNAL(signalSettingsChanged())); 0303 0304 connect(d->setAcceptedThreshold, SIGNAL(valueChanged(int)), 0305 this, SIGNAL(signalSettingsChanged())); 0306 0307 connect(d->setBlurWeight, SIGNAL(valueChanged(int)), 0308 this, SIGNAL(signalSettingsChanged())); 0309 0310 connect(d->setNoiseWeight, SIGNAL(valueChanged(int)), 0311 this, SIGNAL(signalSettingsChanged())); 0312 0313 connect(d->setCompressionWeight, SIGNAL(valueChanged(int)), 0314 this, SIGNAL(signalSettingsChanged())); 0315 0316 // ------------------------------------------------------------------------------ 0317 0318 connect(d->detectBlur, SIGNAL(toggled(bool)), 0319 d->lbl5, SLOT(setEnabled(bool))); 0320 0321 connect(d->detectBlur, SIGNAL(toggled(bool)), 0322 d->setBlurWeight, SLOT(setEnabled(bool))); 0323 0324 connect(d->detectNoise, SIGNAL(toggled(bool)), 0325 d->lbl6, SLOT(setEnabled(bool))); 0326 0327 connect(d->detectNoise, SIGNAL(toggled(bool)), 0328 d->setNoiseWeight, SLOT(setEnabled(bool))); 0329 0330 connect(d->detectCompression, SIGNAL(toggled(bool)), 0331 d->lbl7, SLOT(setEnabled(bool))); 0332 0333 connect(d->detectCompression, SIGNAL(toggled(bool)), 0334 d->setCompressionWeight, SLOT(setEnabled(bool))); 0335 0336 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) 0337 0338 connect(d->detectButtonGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::idClicked), 0339 this, &ImageQualitySettings::slotDisableOptionViews); 0340 0341 #else 0342 0343 connect(d->detectButtonGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), 0344 this, &ImageQualitySettings::slotDisableOptionViews); 0345 0346 #endif 0347 0348 slotDisableOptionViews(); 0349 } 0350 0351 ImageQualitySettings::~ImageQualitySettings() 0352 { 0353 delete d; 0354 } 0355 0356 void ImageQualitySettings::applySettings() 0357 { 0358 ImageQualityContainer imq = getImageQualityContainer(); 0359 imq.writeToConfig(); 0360 } 0361 0362 void ImageQualitySettings::applySettings(KConfigGroup& group) 0363 { 0364 ImageQualityContainer imq = getImageQualityContainer(); 0365 imq.writeToConfig(group); 0366 } 0367 0368 void ImageQualitySettings::readSettings() 0369 { 0370 ImageQualityContainer imq; 0371 imq.readFromConfig(); 0372 setImageQualityContainer(imq); 0373 } 0374 0375 void ImageQualitySettings::readSettings(const KConfigGroup& group) 0376 { 0377 ImageQualityContainer imq; 0378 imq.readFromConfig(group); 0379 setImageQualityContainer(imq); 0380 } 0381 0382 void ImageQualitySettings::setImageQualityContainer(const ImageQualityContainer& imq) 0383 { 0384 d->detectBlur->setChecked(imq.detectBlur); 0385 d->detectNoise->setChecked(imq.detectNoise); 0386 d->detectCompression->setChecked(imq.detectCompression); 0387 d->detectExposure->setChecked(imq.detectExposure); 0388 0389 if (imq.detectAesthetic) 0390 { 0391 d->detectAesthetic->setChecked(true); 0392 } 0393 else 0394 { 0395 d->detectBasicFactors->setChecked(true); 0396 } 0397 0398 d->setRejected->setChecked(imq.lowQRejected); 0399 d->setPending->setChecked(imq.mediumQPending); 0400 d->setAccepted->setChecked(imq.highQAccepted); 0401 d->setRejectedThreshold->setValue(imq.rejectedThreshold); 0402 d->setPendingThreshold->setValue(imq.pendingThreshold); 0403 d->setAcceptedThreshold->setValue(imq.acceptedThreshold); 0404 d->setBlurWeight->setValue(imq.blurWeight); 0405 d->setNoiseWeight->setValue(imq.noiseWeight); 0406 d->setCompressionWeight->setValue(imq.compressionWeight); 0407 0408 d->lbl5->setEnabled(imq.detectBlur); 0409 d->setBlurWeight->setEnabled(imq.detectBlur); 0410 d->lbl6->setEnabled(imq.detectNoise); 0411 d->setNoiseWeight->setEnabled(imq.detectNoise); 0412 d->lbl7->setEnabled(imq.detectCompression); 0413 d->setCompressionWeight->setEnabled(imq.detectCompression); 0414 0415 slotDisableOptionViews(); 0416 } 0417 0418 ImageQualityContainer ImageQualitySettings::getImageQualityContainer() const 0419 { 0420 ImageQualityContainer imq; 0421 0422 imq.detectBlur = d->detectBlur->isChecked(); 0423 imq.detectNoise = d->detectNoise->isChecked(); 0424 imq.detectCompression = d->detectCompression->isChecked(); 0425 imq.detectExposure = d->detectExposure->isChecked(); 0426 imq.detectAesthetic = d->detectAesthetic->isChecked(); 0427 imq.lowQRejected = d->setRejected->isChecked(); 0428 imq.mediumQPending = d->setPending->isChecked(); 0429 imq.highQAccepted = d->setAccepted->isChecked(); 0430 imq.rejectedThreshold = d->setRejectedThreshold->value(); 0431 imq.pendingThreshold = d->setPendingThreshold->value(); 0432 imq.acceptedThreshold = d->setAcceptedThreshold->value(); 0433 imq.blurWeight = d->setBlurWeight->value(); 0434 imq.noiseWeight = d->setNoiseWeight->value(); 0435 imq.compressionWeight = d->setCompressionWeight->value(); 0436 0437 return imq; 0438 } 0439 0440 void ImageQualitySettings::slotDisableOptionViews() 0441 { 0442 bool b = d->detectBasicFactors->isChecked(); 0443 0444 d->lbl2->setEnabled(b); 0445 d->lbl3->setEnabled(b); 0446 d->lbl4->setEnabled(b); 0447 d->detectBlur->setEnabled(b); 0448 d->detectNoise->setEnabled(b); 0449 d->detectCompression->setEnabled(b); 0450 d->detectExposure->setEnabled(b); 0451 d->setRejectedThreshold->setEnabled(b); 0452 d->setPendingThreshold->setEnabled(b); 0453 d->setAcceptedThreshold->setEnabled(b); 0454 0455 d->lbl5->setEnabled(b && d->detectBlur->isChecked()); 0456 d->setBlurWeight->setEnabled(b && d->detectBlur->isChecked()); 0457 d->lbl6->setEnabled(b && d->detectNoise->isChecked()); 0458 d->setNoiseWeight->setEnabled(b && d->detectNoise->isChecked()); 0459 d->lbl7->setEnabled(b && d->detectCompression->isChecked()); 0460 d->setCompressionWeight->setEnabled(b && d->detectCompression->isChecked()); 0461 0462 Q_EMIT signalSettingsChanged(); 0463 } 0464 0465 void ImageQualitySettings::resetToDefault() 0466 { 0467 blockSignals(true); 0468 0469 ImageQualityContainer prm; 0470 setImageQualityContainer(prm); 0471 0472 blockSignals(false); 0473 } 0474 0475 ImageQualityContainer ImageQualitySettings::defaultSettings() const 0476 { 0477 ImageQualityContainer prm; 0478 0479 return prm; 0480 } 0481 0482 } // namespace Digikam 0483 0484 #include "moc_imagequalitysettings.cpp"