1 /* ============================================================
2  *
3  * Date        : 2008-02-10
4  * Description : a tool to fix automatically camera lens aberrations
5  *
6  * Copyright (C) 2008      by Adrian Schroeter <adrian at suse dot de>
7  * Copyright (C) 2008-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
8  *
9  * This program is free software; you can redistribute it
10  * and/or modify it under the terms of the GNU General
11  * Public License as published by the Free Software Foundation;
12  * either version 2, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * ============================================================ */
20 
21 #include "lensfuncameraselector.h"
22 
23 // Qt includes
24 
25 #include <QCheckBox>
26 #include <QGridLayout>
27 #include <QLabel>
28 #include <QString>
29 #include <QWidget>
30 #include <QApplication>
31 #include <QStyle>
32 
33 // KDE includes
34 
35 #include <kconfiggroup.h>
36 #include <klocalizedstring.h>
37 
38 // Local includes
39 
40 #include "dlayoutbox.h"
41 #include "digikam_debug.h"
42 #include "squeezedcombobox.h"
43 #include "dnuminput.h"
44 #include "dexpanderbox.h"
45 
46 // Disable deprecated API from Lensfun.
47 #if defined(Q_CC_GNU)
48 #   pragma GCC diagnostic push
49 #   pragma GCC diagnostic ignored "-Wdeprecated-declarations"
50 #endif
51 
52 #if defined(Q_CC_CLANG)
53 #   pragma clang diagnostic push
54 #   pragma clang diagnostic ignored "-Wdeprecated-declarations"
55 #endif
56 
57 namespace Digikam
58 {
59 
60 class Q_DECL_HIDDEN LensFunCameraSelector::Private
61 {
62 public:
63 
Private()64     explicit Private()
65         : passiveMetadataUsage  (false),
66           metadataUsage         (nullptr),
67           metadataResult        (nullptr),
68           makeLabel             (nullptr),
69           modelLabel            (nullptr),
70           lensLabel             (nullptr),
71           focalLabel            (nullptr),
72           aperLabel             (nullptr),
73           distLabel             (nullptr),
74           configUseMetadata     (QLatin1String("UseMetadata")),
75           configCameraModel     (QLatin1String("CameraModel")),
76           configCameraMake      (QLatin1String("CameraMake")),
77           configLensModel       (QLatin1String("LensModel")),
78           configSubjectDistance (QLatin1String("SubjectDistance")),
79           configFocalLength     (QLatin1String("FocalLength")),
80           configCropFactor      (QLatin1String("CropFactor")),
81           configAperture        (QLatin1String("Aperture")),
82           redStyle              (QLatin1String("QLabel {color: red;}")),
83           orangeStyle           (QLatin1String("QLabel {color: orange;}")),
84           greenStyle            (QLatin1String("QLabel {color: green;}")),
85           lensDescription       (nullptr),
86           makeDescription       (nullptr),
87           modelDescription      (nullptr),
88           make                  (nullptr),
89           model                 (nullptr),
90           lens                  (nullptr),
91           focal                 (nullptr),
92           aperture              (nullptr),
93           distance              (nullptr),
94           metadata              (nullptr),
95           iface                 (nullptr)
96     {
97     }
98 
99     bool                passiveMetadataUsage;
100 
101     QCheckBox*          metadataUsage;
102     QLabel*             metadataResult;
103     QLabel*             makeLabel;
104     QLabel*             modelLabel;
105     QLabel*             lensLabel;
106     QLabel*             focalLabel;
107     QLabel*             aperLabel;
108     QLabel*             distLabel;
109 
110     const QString       configUseMetadata;
111     const QString       configCameraModel;
112     const QString       configCameraMake;
113     const QString       configLensModel;
114     const QString       configSubjectDistance;
115     const QString       configFocalLength;
116     const QString       configCropFactor;
117     const QString       configAperture;
118     const QString       redStyle;
119     const QString       orangeStyle;
120     const QString       greenStyle;
121 
122     DAdjustableLabel*   lensDescription;
123     DAdjustableLabel*   makeDescription;
124     DAdjustableLabel*   modelDescription;
125 
126     SqueezedComboBox*   make;
127     SqueezedComboBox*   model;
128     SqueezedComboBox*   lens;
129 
130     DDoubleNumInput*    focal;
131     DDoubleNumInput*    aperture;
132     DDoubleNumInput*    distance;
133 
134     DMetadata*          metadata;
135 
136     LensFunIface*       iface;
137 };
138 
LensFunCameraSelector(QWidget * const parent)139 LensFunCameraSelector::LensFunCameraSelector(QWidget* const parent)
140     : QWidget(parent),
141       d      (new Private)
142 {
143     d->iface                = new LensFunIface();
144 
145     QGridLayout* const grid = new QGridLayout(this);
146     DHBox* const hbox       = new DHBox(this);
147     d->metadataUsage        = new QCheckBox(i18n("Use Metadata"), hbox);
148     QLabel* const space     = new QLabel(hbox);
149     d->metadataResult       = new QLabel(hbox);
150     hbox->setStretchFactor(space, 10);
151 
152     DHBox* const hbox1      = new DHBox(this);
153     d->makeLabel            = new QLabel(i18nc("camera make",  "Make:"),  hbox1);
154     QLabel* const space1    = new QLabel(hbox1);
155     d->makeDescription      = new DAdjustableLabel(hbox1);
156     hbox1->setStretchFactor(space1, 10);
157     d->makeDescription->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
158     d->makeDescription->setWhatsThis(i18n("This is the camera maker description string found in image meta-data. "
159                                           "This one is used to query and find relevant camera device information from Lensfun database."));
160 
161     d->make                 = new SqueezedComboBox(this);
162     d->make->setCurrentIndex(0);
163 
164     DHBox* const hbox2      = new DHBox(this);
165     d->modelLabel           = new QLabel(i18nc("camera model", "Model:"), hbox2);
166     QLabel* const space2    = new QLabel(hbox2);
167     d->modelDescription     = new DAdjustableLabel(hbox2);
168     hbox2->setStretchFactor(space2, 10);
169     d->modelDescription->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
170     d->modelDescription->setWhatsThis(i18n("This is the camera model description string found in image meta-data. "
171                                            "This one is used to query and found relevant camera device information from Lensfun database."));
172 
173     d->model                = new SqueezedComboBox(this);
174     d->model->setCurrentIndex(0);
175 
176     DHBox* const hbox3      = new DHBox(this);
177     d->lensLabel            = new QLabel(i18nc("camera lens",  "Lens:"),  hbox3);
178     QLabel* const space3    = new QLabel(hbox3);
179     d->lensDescription      = new DAdjustableLabel(hbox3);
180 
181     // Workaround for layout problem with long lens names.
182 
183     d->lensDescription->setAdjustedText(QString(40, QLatin1Char(' ')));
184     d->lensDescription->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
185     d->lensDescription->setWhatsThis(i18n("This is the lens description string found in image meta-data. "
186                                           "This one is used to query and found relevant lens information from Lensfun database."));
187     hbox3->setStretchFactor(space3, 10);
188 
189     d->lens                 = new SqueezedComboBox(this);
190     d->lens->setCurrentIndex(0);
191 
192     d->metadataUsage->setEnabled(false);
193     d->metadataUsage->setCheckState(Qt::Unchecked);
194     d->metadataUsage->setWhatsThis(i18n("Set this option to try to guess the right camera/lens settings "
195                                         "from the image metadata (as Exif or XMP)."));
196 
197     d->focalLabel           = new QLabel(i18n("Focal Length (mm):"), this);
198     d->aperLabel            = new QLabel(i18n("Aperture:"), this);
199     d->distLabel            = new QLabel(i18n("Subject Distance (m):"), this);
200 
201     d->focal                = new DDoubleNumInput(this);
202     d->focal->setDecimals(1);
203     d->focal->setRange(1.0, 10000.0, 0.01);
204     d->focal->setDefaultValue(1.0);
205 
206     d->aperture             = new DDoubleNumInput(this);
207     d->aperture->setDecimals(1);
208     d->aperture->setRange(1.1, 256.0, 0.1);
209     d->aperture->setDefaultValue(1.1);
210 
211     d->distance             = new DDoubleNumInput(this);
212     d->distance->setDecimals(1);
213     d->distance->setRange(0.0, 10000.0, 0.1);
214     d->distance->setDefaultValue(0.0);
215 
216     grid->addWidget(hbox,          0, 0, 1, 3);
217     grid->addWidget(hbox1,         1, 0, 1, 3);
218     grid->addWidget(d->make,       2, 0, 1, 3);
219     grid->addWidget(hbox2,         3, 0, 1, 3);
220     grid->addWidget(d->model,      4, 0, 1, 3);
221     grid->addWidget(hbox3,         5, 0, 1, 3);
222     grid->addWidget(d->lens,       6, 0, 1, 3);
223     grid->addWidget(d->focalLabel, 7, 0, 1, 1);
224     grid->addWidget(d->focal,      7, 1, 1, 2);
225     grid->addWidget(d->aperLabel,  8, 0, 1, 1);
226     grid->addWidget(d->aperture,   8, 1, 1, 2);
227     grid->addWidget(d->distLabel,  9, 0, 1, 1);
228     grid->addWidget(d->distance,   9, 1, 1, 2);
229     grid->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
230     grid->setContentsMargins(QMargins());
231 
232     connect(d->metadataUsage, SIGNAL(toggled(bool)),
233             this, SLOT(slotUseMetadata(bool)));
234 
235     connect(d->make, SIGNAL(currentIndexChanged(int)),
236             this, SLOT(slotMakeSelected()));
237 
238     connect(d->model, SIGNAL(currentIndexChanged(int)),
239             this, SLOT(slotModelChanged()));
240 
241     connect(d->lens, SIGNAL(currentIndexChanged(int)),
242             this, SLOT(slotLensSelected()));
243 
244     connect(d->focal, SIGNAL(valueChanged(double)),
245             this, SLOT(slotFocalChanged()));
246 
247     connect(d->aperture, SIGNAL(valueChanged(double)),
248             this, SLOT(slotApertureChanged()));
249 
250     connect(d->distance, SIGNAL(valueChanged(double)),
251             this, SLOT(slotDistanceChanged()));
252 
253     populateDeviceCombos();
254     populateLensCombo();
255 }
256 
~LensFunCameraSelector()257 LensFunCameraSelector::~LensFunCameraSelector()
258 {
259     delete d->metadata;
260     delete d->iface;
261     delete d;
262 }
263 
iface() const264 LensFunIface* LensFunCameraSelector::iface() const
265 {
266     return d->iface;
267 }
268 
settings()269 LensFunContainer LensFunCameraSelector::settings()
270 {
271     // Update settings in LensFun interface
272 
273     blockSignals(true);
274 
275     slotModelSelected();
276     slotLensSelected();
277     slotFocalChanged();
278     slotApertureChanged();
279     slotDistanceChanged();
280 
281     blockSignals(false);
282 
283     return d->iface->settings();
284 }
285 
setSettings(const LensFunContainer & settings)286 void LensFunCameraSelector::setSettings(const LensFunContainer& settings)
287 {
288     blockSignals(true);
289 
290     d->iface->setSettings(settings);
291     refreshSettingsView();
292 
293     blockSignals(false);
294 }
295 
resetToDefault()296 void LensFunCameraSelector::resetToDefault()
297 {
298     setUseMetadata(true);
299 }
300 
readSettings(KConfigGroup & group)301 void LensFunCameraSelector::readSettings(KConfigGroup& group)
302 {
303     setUseMetadata(group.readEntry(d->configUseMetadata, true));
304 
305     if (!useMetadata())
306     {
307         LensFunContainer settings = d->iface->settings();
308         settings.cameraModel      = group.readEntry(d->configCameraModel, QString());
309         settings.cameraMake       = group.readEntry(d->configCameraMake,  QString());
310         settings.lensModel        = group.readEntry(d->configLensModel,   QString());
311 
312         if (settings.subjectDistance <= 0.0)
313         {
314             settings.subjectDistance = group.readEntry(d->configSubjectDistance, -1.0);
315         }
316 
317         if (settings.focalLength <= 0.0)
318         {
319             settings.focalLength = group.readEntry(d->configFocalLength, -1.0);
320         }
321 
322         settings.cropFactor = group.readEntry(d->configCropFactor, -1.0);
323 
324         if (settings.aperture <= 0.0)
325         {
326             settings.aperture = group.readEntry(d->configAperture, -1.0);
327         }
328 
329         setSettings(settings);
330     }
331 
332     slotUseMetadata(useMetadata());
333 }
334 
writeSettings(KConfigGroup & group)335 void LensFunCameraSelector::writeSettings(KConfigGroup& group)
336 {
337     group.writeEntry(d->configUseMetadata,     useMetadata());
338     group.writeEntry(d->configCameraModel,     d->iface->settings().cameraModel);
339     group.writeEntry(d->configCameraMake,      d->iface->settings().cameraMake);
340     group.writeEntry(d->configLensModel,       d->iface->settings().lensModel);
341     group.writeEntry(d->configSubjectDistance, d->iface->settings().subjectDistance);
342     group.writeEntry(d->configFocalLength,     d->iface->settings().focalLength);
343     group.writeEntry(d->configCropFactor,      d->iface->settings().cropFactor);
344     group.writeEntry(d->configAperture,        d->iface->settings().aperture);
345 }
346 
setMetadata(const MetaEngineData & meta)347 void LensFunCameraSelector::setMetadata(const MetaEngineData& meta)
348 {
349     if (d->metadata)
350     {
351         delete d->metadata;
352     }
353 
354     d->metadata = new DMetadata(meta);
355 
356     if (d->metadata->isEmpty())
357     {
358         d->metadataUsage->setCheckState(Qt::Unchecked);
359         setEnabledUseMetadata(false);
360     }
361     else
362     {
363         setEnabledUseMetadata(true);
364         findFromMetadata();
365     }
366 }
367 
setEnabledUseMetadata(bool b)368 void LensFunCameraSelector::setEnabledUseMetadata(bool b)
369 {
370     d->metadataUsage->setEnabled(b);
371 }
372 
setUseMetadata(bool b)373 void LensFunCameraSelector::setUseMetadata(bool b)
374 {
375     d->metadataUsage->setChecked(b);
376 }
377 
useMetadata() const378 bool LensFunCameraSelector::useMetadata() const
379 {
380     return (d->metadataUsage->isChecked());
381 }
382 
setPassiveMetadataUsage(bool b)383 void LensFunCameraSelector::setPassiveMetadataUsage(bool b)
384 {
385     d->passiveMetadataUsage = b;
386 }
387 
slotUseMetadata(bool b)388 void LensFunCameraSelector::slotUseMetadata(bool b)
389 {
390     d->makeDescription->setAdjustedText();
391     d->modelDescription->setAdjustedText();
392     d->lensDescription->setAdjustedText();
393     d->metadataResult->clear();
394     d->makeLabel->setStyleSheet(qApp->styleSheet());
395     d->modelLabel->setStyleSheet(qApp->styleSheet());
396     d->lensLabel->setStyleSheet(qApp->styleSheet());
397     d->focalLabel->setStyleSheet(qApp->styleSheet());
398     d->aperLabel->setStyleSheet(qApp->styleSheet());
399     d->distLabel->setStyleSheet(qApp->styleSheet());
400     d->make->setEnabled(true);
401     d->model->setEnabled(true);
402     d->lens->setEnabled(true);
403     d->focal->setEnabled(true);
404     d->aperture->setEnabled(true);
405     d->distance->setEnabled(true);
406 
407     if (b)
408     {
409         if (d->passiveMetadataUsage)
410         {
411             d->make->setEnabled(false);
412             d->model->setEnabled(false);
413             d->lens->setEnabled(false);
414             d->focal->setEnabled(false);
415             d->aperture->setEnabled(false);
416             d->distance->setEnabled(false);
417             emit signalLensSettingsChanged();
418         }
419         else
420         {
421             LensFunIface::MetadataMatch ret = findFromMetadata();
422 
423             switch (ret)
424             {
425                 case LensFunIface::MetadataUnavailable:
426                     d->metadataResult->setText(i18n("(no metadata available)"));
427                     d->metadataResult->setStyleSheet(d->redStyle);
428                     break;
429 
430                 case LensFunIface::MetadataNoMatch:
431                     d->metadataResult->setText(i18n("(no match found)"));
432                     d->metadataResult->setStyleSheet(d->redStyle);
433                     break;
434 
435                 case LensFunIface::MetadataPartialMatch:
436                     d->metadataResult->setText(i18n("(partial match found)"));
437                     d->metadataResult->setStyleSheet(d->orangeStyle);
438                     break;
439 
440                 default:
441                     d->metadataResult->setText(i18n("(exact match found)"));
442                     d->metadataResult->setStyleSheet(d->greenStyle);
443                     break;
444             }
445         }
446     }
447 }
448 
findFromMetadata()449 LensFunIface::MetadataMatch LensFunCameraSelector::findFromMetadata()
450 {
451     LensFunIface::MetadataMatch ret = d->iface->findFromMetadata(d->metadata);
452     refreshSettingsView();
453     slotModelSelected();
454     slotLensSelected();
455 
456     return ret;
457 }
458 
refreshSettingsView()459 void LensFunCameraSelector::refreshSettingsView()
460 {
461     d->make->blockSignals(true);
462     d->model->blockSignals(true);
463     d->lens->blockSignals(true);
464 
465     d->makeLabel->setStyleSheet(qApp->styleSheet());
466     d->modelLabel->setStyleSheet(qApp->styleSheet());
467     d->lensLabel->setStyleSheet(qApp->styleSheet());
468     d->focalLabel->setStyleSheet(qApp->styleSheet());
469     d->aperLabel->setStyleSheet(qApp->styleSheet());
470     d->distLabel->setStyleSheet(qApp->styleSheet());
471 
472     if (!d->passiveMetadataUsage)
473     {
474         d->makeDescription->setAdjustedText(QString::fromLatin1("<i>%1</i>").arg(d->iface->makeDescription()));
475     }
476 
477     int makerIdx = -1;
478 
479     if (d->iface->usedCamera())
480     {
481         makerIdx = d->make->findOriginalText(d->iface->settings().cameraMake);
482         qCDebug(DIGIKAM_DIMG_LOG) << "makerIdx: " << makerIdx << " (" << d->iface->settings().cameraMake << ")";
483     }
484     else
485     {
486         int i = d->make->findOriginalText(d->iface->makeDescription());
487 
488         if (i == -1)
489         {
490             i = d->make->findOriginalText(QLatin1String("Generic"));
491         }
492 
493         if (i >= 0)
494         {
495             d->make->setCurrentIndex(i);
496             populateDeviceCombos();
497         }
498 
499         if (!d->passiveMetadataUsage)
500         {
501             d->makeLabel->setStyleSheet(d->orangeStyle);
502         }
503     }
504 
505     if (makerIdx >= 0)
506     {
507         d->make->setCurrentIndex(makerIdx);
508         d->make->setEnabled(d->passiveMetadataUsage);
509 
510         if (!d->passiveMetadataUsage)
511         {
512             d->makeLabel->setStyleSheet(d->greenStyle);
513         }
514 
515         populateDeviceCombos();
516     }
517 
518     // ------------------------------------------------------------------------------------------------
519 
520     if (!d->passiveMetadataUsage)
521     {
522         d->modelDescription->setAdjustedText(QString::fromLatin1("<i>%1</i>").arg(d->iface->modelDescription()));
523     }
524 
525     int modelIdx = -1;
526 
527     if (d->iface->usedCamera())
528     {
529         modelIdx = d->model->findOriginalText(d->iface->settings().cameraModel);
530         qCDebug(DIGIKAM_DIMG_LOG) << "modelIdx: " << modelIdx << " (" << d->iface->settings().cameraModel << ")";
531     }
532 
533     if (modelIdx >= 0)
534     {
535         d->model->setCurrentIndex(modelIdx);
536         d->model->setEnabled(d->passiveMetadataUsage);
537 
538         if (!d->passiveMetadataUsage)
539         {
540             d->modelLabel->setStyleSheet(d->greenStyle);
541         }
542 
543         populateLensCombo();
544     }
545     else
546     {
547         if (!d->passiveMetadataUsage)
548         {
549             d->modelLabel->setStyleSheet(d->orangeStyle);
550         }
551     }
552 
553     // ------------------------------------------------------------------------------------------------
554 
555     if (!d->passiveMetadataUsage)
556     {
557         d->lensDescription->setAdjustedText(QString::fromLatin1("<i>%1</i>").arg(d->iface->lensDescription()));
558     }
559 
560     int lensIdx = -1;
561 
562     if (d->iface->usedLens())
563     {
564         lensIdx = d->lens->findOriginalText(d->iface->settings().lensModel);
565         qCDebug(DIGIKAM_DIMG_LOG) << "lensIdx: " << lensIdx << " (" << d->iface->settings().lensModel << ")";
566     }
567 
568     if (lensIdx >= 0)
569     {
570         // found lens model directly, best case :)
571 
572         d->lens->setCurrentIndex(lensIdx);
573         d->lens->setEnabled(d->passiveMetadataUsage);
574 
575         if (!d->passiveMetadataUsage)
576         {
577             d->lensLabel->setStyleSheet(d->greenStyle);
578         }
579     }
580     else
581     {
582         if (!d->passiveMetadataUsage)
583         {
584             d->lensLabel->setStyleSheet(d->orangeStyle);
585         }
586     }
587 
588     // ------------------------------------------------------------------------------------------------
589 
590     if (d->iface->settings().focalLength != -1.0)
591     {
592         d->focal->setValue(d->iface->settings().focalLength);
593         d->focal->setEnabled(d->passiveMetadataUsage);
594 
595         if (!d->passiveMetadataUsage)
596         {
597             d->focalLabel->setStyleSheet(d->greenStyle);
598         }
599     }
600     else
601     {
602         if (!d->passiveMetadataUsage)
603         {
604             d->focalLabel->setStyleSheet(d->orangeStyle);
605         }
606     }
607 
608     if (d->iface->settings().aperture != -1.0)
609     {
610         d->aperture->setValue(d->iface->settings().aperture);
611         d->aperture->setEnabled(d->passiveMetadataUsage);
612 
613         if (!d->passiveMetadataUsage)
614         {
615             d->aperLabel->setStyleSheet(d->greenStyle);
616         }
617     }
618     else
619     {
620         if (!d->passiveMetadataUsage)
621         {
622             d->aperLabel->setStyleSheet(d->orangeStyle);
623         }
624     }
625 
626     if (d->iface->settings().subjectDistance != -1.0)
627     {
628         d->distance->setValue(d->iface->settings().subjectDistance);
629         d->distance->setEnabled(d->passiveMetadataUsage);
630 
631         if (!d->passiveMetadataUsage)
632         {
633             d->distLabel->setStyleSheet(d->greenStyle);
634         }
635     }
636     else
637     {
638         if (!d->passiveMetadataUsage)
639         {
640             d->distLabel->setStyleSheet(d->orangeStyle);
641         }
642     }
643 
644     d->make->blockSignals(false);
645     d->model->blockSignals(false);
646     d->lens->blockSignals(false);
647 }
648 
populateDeviceCombos()649 void LensFunCameraSelector::populateDeviceCombos()
650 {
651     d->make->blockSignals(true);
652     d->model->blockSignals(true);
653 
654     const lfCamera* const* it = d->iface->lensFunCameras();
655 
656     // reset box
657 
658     d->model->clear();
659 
660     bool firstRun = false;
661 
662     if (d->make->count() == 0)
663     {
664         firstRun = true;
665     }
666 
667     while (*it)
668     {
669         if (firstRun)
670         {
671             // Maker DB does not change, so we fill it only once.
672 
673             if ((*it)->Maker)
674             {
675                 QString t = QLatin1String((*it)->Maker);
676 
677                 if (d->make->findOriginalText(t) < 0)
678                 {
679                     d->make->addSqueezedItem(t);
680                 }
681             }
682         }
683 
684         // Fill models for current selected maker
685 
686         if ((*it)->Model && QLatin1String((*it)->Maker) == d->make->itemHighlighted())
687         {
688             LensFunIface::DevicePtr dev = *it;
689             QVariant b                  = qVariantFromValue(dev);
690             d->model->addSqueezedItem(QLatin1String(dev->Model), b);
691         }
692 
693         ++it;
694     }
695 
696     d->make->blockSignals(false);
697     d->model->blockSignals(false);
698 }
699 
populateLensCombo()700 void LensFunCameraSelector::populateLensCombo()
701 {
702     d->lens->blockSignals(true);
703     d->lens->clear();
704     d->lens->blockSignals(false);
705 
706     QVariant v = d->model->itemData(d->model->currentIndex());
707 
708     if (!v.isValid() || v.isNull())
709     {
710         qCDebug(DIGIKAM_DIMG_LOG) << "Invalid variant value for device!";
711         return;
712     }
713 
714     qCDebug(DIGIKAM_DIMG_LOG) << "variant: " << v;
715 
716     LensFunIface::DevicePtr dev = v.value<LensFunIface::DevicePtr>();
717 
718     if (!dev)
719     {
720         qCDebug(DIGIKAM_DIMG_LOG) << "Device is null!";
721         return;
722     }
723 
724     qCDebug(DIGIKAM_DIMG_LOG) << "dev: " << dev->Maker << " :: " << dev->Model << " :: " << dev->CropFactor;
725 
726     d->lens->blockSignals(true);
727     const lfLens** lenses     = d->iface->lensFunDataBase()->FindLenses(dev, nullptr, nullptr);
728     LensFunContainer settings = d->iface->settings();
729     settings.cropFactor       = dev ? dev->CropFactor : -1.0;
730     d->iface->setSettings(settings);
731 
732     QMultiMap<QString, QVariant> lensMap;
733 
734     while (lenses && *lenses)
735     {
736         LensFunIface::LensPtr lens = *lenses;
737         QVariant b                 = qVariantFromValue(lens);
738         lensMap.insert(QLatin1String(lens->Model), b);
739         ++lenses;
740     }
741 
742     QMultiMap<QString, QVariant>::ConstIterator it = lensMap.constBegin();
743 
744     for ( ; it != lensMap.constEnd() ; ++it)
745     {
746         d->lens->addSqueezedItem(it.key(), it.value());
747     }
748 
749     d->lens->blockSignals(false);
750 }
751 
slotMakeSelected()752 void LensFunCameraSelector::slotMakeSelected()
753 {
754     populateDeviceCombos();
755     slotModelSelected();
756 
757     // Fill Lens list for current Maker & Model and fire signalLensSettingsChanged().
758 
759     populateLensCombo();
760     slotLensSelected();
761 }
762 
slotModelChanged()763 void LensFunCameraSelector::slotModelChanged()
764 {
765     populateLensCombo();
766     slotModelSelected();
767 }
768 
slotModelSelected()769 void LensFunCameraSelector::slotModelSelected()
770 {
771     QVariant v = d->model->itemData(d->model->currentIndex());
772     d->iface->setUsedCamera(d->metadataUsage->isChecked() && d->passiveMetadataUsage ? nullptr :
773                             v.value<LensFunIface::DevicePtr>());
774     emit signalLensSettingsChanged();
775 }
776 
slotLensSelected()777 void LensFunCameraSelector::slotLensSelected()
778 {
779     QVariant v = d->lens->itemData(d->lens->currentIndex());
780     d->iface->setUsedLens(d->metadataUsage->isChecked() && d->passiveMetadataUsage ? nullptr :
781                           v.value<LensFunIface::LensPtr>());
782 
783     LensFunContainer settings = d->iface->settings();
784 
785     if (d->iface->usedLens() &&
786         (settings.cropFactor <= 0.0)) // this should not happen
787     {
788         qCDebug(DIGIKAM_DIMG_LOG) << "No crop factor is set for camera, using lens calibration data: "
789                                   << d->iface->usedLens()->CropFactor;
790         settings.cropFactor = d->iface->usedLens()->CropFactor;
791     }
792 
793     d->iface->setSettings(settings);
794     emit signalLensSettingsChanged();
795 }
796 
slotFocalChanged()797 void LensFunCameraSelector::slotFocalChanged()
798 {
799     LensFunContainer settings = d->iface->settings();
800     settings.focalLength      = d->metadataUsage->isChecked() && d->passiveMetadataUsage ? -1.0
801                                                                                          : d->focal->value();
802     d->iface->setSettings(settings);
803     emit signalLensSettingsChanged();
804 }
805 
slotApertureChanged()806 void LensFunCameraSelector::slotApertureChanged()
807 {
808     LensFunContainer settings = d->iface->settings();
809     settings.aperture         = d->metadataUsage->isChecked() && d->passiveMetadataUsage ? -1.0
810                                                                                          : d->aperture->value();
811     d->iface->setSettings(settings);
812     emit signalLensSettingsChanged();
813 }
814 
slotDistanceChanged()815 void LensFunCameraSelector::slotDistanceChanged()
816 {
817     LensFunContainer settings = d->iface->settings();
818     settings.subjectDistance  = d->metadataUsage->isChecked() && d->passiveMetadataUsage ? -1.0
819                                                                                          : d->distance->value();
820     d->iface->setSettings(settings);
821     emit signalLensSettingsChanged();
822 }
823 
824 } // namespace Digikam
825 
826 // Restore warnings
827 
828 #if defined(Q_CC_GNU)
829 #   pragma GCC diagnostic pop
830 #endif
831 
832 #if defined(Q_CC_CLANG)
833 #   pragma clang diagnostic pop
834 #endif
835