File indexing completed on 2025-01-19 03:51:22

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2006-10-18
0007  * Description : EXIF device settings page.
0008  *
0009  * SPDX-FileCopyrightText: 2006-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 "exifdevice.h"
0016 
0017 // C++ includes
0018 
0019 #include <cmath>
0020 
0021 // Qt includes
0022 
0023 #include <QLabel>
0024 #include <QGridLayout>
0025 #include <QApplication>
0026 #include <QStyle>
0027 #include <QComboBox>
0028 #include <QSpinBox>
0029 #include <QLineEdit>
0030 #include <QValidator>
0031 
0032 // KDE includes
0033 
0034 #include <klocalizedstring.h>
0035 
0036 // Local includes
0037 
0038 #include "dlayoutbox.h"
0039 #include "metadatacheckbox.h"
0040 #include "dexpanderbox.h"
0041 
0042 namespace DigikamGenericMetadataEditPlugin
0043 {
0044 
0045 class Q_DECL_HIDDEN EXIFDevice::Private
0046 {
0047 public:
0048 
0049     explicit Private()
0050     {
0051         makeCheck                = nullptr;
0052         modelCheck               = nullptr;
0053         deviceTypeCheck          = nullptr;
0054         exposureTimeCheck        = nullptr;
0055         exposureProgramCheck     = nullptr;
0056         exposureModeCheck        = nullptr;
0057         exposureBiasCheck        = nullptr;
0058         ISOSpeedCheck            = nullptr;
0059         meteringModeCheck        = nullptr;
0060         sensingMethodCheck       = nullptr;
0061         sceneTypeCheck           = nullptr;
0062         subjectDistanceTypeCheck = nullptr;
0063         exposureProgramCB        = nullptr;
0064         exposureModeCB           = nullptr;
0065         ISOSpeedCB               = nullptr;
0066         meteringModeCB           = nullptr;
0067         sensingMethodCB          = nullptr;
0068         sceneTypeCB              = nullptr;
0069         subjectDistanceTypeCB    = nullptr;
0070         exposureTimeNumEdit      = nullptr;
0071         exposureTimeDenEdit      = nullptr;
0072         exposureBiasEdit         = nullptr;
0073         makeEdit                 = nullptr;
0074         modelEdit                = nullptr;
0075         deviceTypeCB             = nullptr;
0076     }
0077 
0078     QCheckBox*        makeCheck;
0079     QCheckBox*        modelCheck;
0080     QCheckBox*        exposureTimeCheck;
0081     QCheckBox*        exposureBiasCheck;
0082 
0083     QComboBox*        deviceTypeCB;
0084     QComboBox*        exposureProgramCB;
0085     QComboBox*        exposureModeCB;
0086     QComboBox*        ISOSpeedCB;
0087     QComboBox*        meteringModeCB;
0088     QComboBox*        sensingMethodCB;
0089     QComboBox*        sceneTypeCB;
0090     QComboBox*        subjectDistanceTypeCB;
0091 
0092     QLineEdit*        makeEdit;
0093     QLineEdit*        modelEdit;
0094 
0095     QSpinBox*         exposureTimeNumEdit;
0096     QSpinBox*         exposureTimeDenEdit;
0097 
0098     QDoubleSpinBox*   exposureBiasEdit;
0099 
0100     MetadataCheckBox* deviceTypeCheck;
0101     MetadataCheckBox* exposureProgramCheck;
0102     MetadataCheckBox* exposureModeCheck;
0103     MetadataCheckBox* meteringModeCheck;
0104     MetadataCheckBox* ISOSpeedCheck;
0105     MetadataCheckBox* sensingMethodCheck;
0106     MetadataCheckBox* sceneTypeCheck;
0107     MetadataCheckBox* subjectDistanceTypeCheck;
0108 };
0109 
0110 EXIFDevice::EXIFDevice(QWidget* const parent)
0111     : MetadataEditPage(parent),
0112       d               (new Private)
0113 {
0114     QGridLayout* const grid = new QGridLayout(widget());
0115 
0116     // EXIF only accept printable Ascii char.
0117 
0118     QRegularExpression asciiRx(QLatin1String("[\x20-\x7F]+$"));
0119     QValidator* const asciiValidator = new QRegularExpressionValidator(asciiRx, this);
0120 
0121     // --------------------------------------------------------
0122 
0123     d->makeCheck = new QCheckBox(i18n("Device manufacturer (*):"), this);
0124     d->makeEdit  = new QLineEdit(this);
0125     d->makeEdit->setClearButtonEnabled(true);
0126     d->makeEdit->setValidator(asciiValidator);
0127     d->makeEdit->setPlaceholderText(i18n("Set here the manufacturer name"));
0128     d->makeEdit->setWhatsThis(i18n("Set here the manufacturer of image input equipment used to "
0129                                    "take the picture. This field is limited to ASCII characters."));
0130 
0131     // --------------------------------------------------------
0132 
0133     d->modelCheck = new QCheckBox(i18n("Device model (*):"), this);
0134     d->modelEdit  = new QLineEdit(this);
0135     d->modelEdit->setClearButtonEnabled(true);
0136     d->modelEdit->setValidator(asciiValidator);
0137     d->modelEdit->setPlaceholderText(i18n("Set here the model name"));
0138     d->modelEdit->setWhatsThis(i18n("Set here the model of image input equipment used to "
0139                                     "take the picture. This field is limited to ASCII characters."));
0140 
0141     // --------------------------------------------------------
0142 
0143     d->deviceTypeCheck = new MetadataCheckBox(i18n("Device type:"), this);
0144     d->deviceTypeCB    = new QComboBox(this);
0145     d->deviceTypeCB->insertItem(0, i18n("Film scanner"));
0146     d->deviceTypeCB->insertItem(1, i18n("Reflection print scanner"));
0147     d->deviceTypeCB->insertItem(2, i18n("Digital still camera"));
0148     d->deviceTypeCB->setWhatsThis(i18n("Select here the image input equipment type used to "
0149                                        "take the picture."));
0150 
0151     QLabel* const warning = new QLabel(i18n("<b>Warning:</b> Exif<b><a href="
0152                  "'https://en.wikipedia.org/wiki/Exchangeable_image_file_format#MakerNote_data'>"
0153                  "Makernotes</a></b> can be unreadable if you set "
0154                  "wrong device manufacturer/model description."), this);
0155     warning->setOpenExternalLinks(true);
0156     warning->setWordWrap(true);
0157     warning->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
0158 
0159     DLineWidget* const line = new DLineWidget(Qt::Horizontal, this);
0160 
0161     // --------------------------------------------------------
0162 
0163     d->exposureTimeCheck        = new QCheckBox(i18n("Exposure time (seconds):"), this);
0164     d->exposureTimeNumEdit      = new QSpinBox(this);
0165     d->exposureTimeNumEdit->setMinimum(1);
0166     d->exposureTimeNumEdit->setMaximum(100000);
0167     d->exposureTimeNumEdit->setSingleStep(1);
0168     d->exposureTimeNumEdit->setValue(1);
0169     d->exposureTimeDenEdit      = new QSpinBox(this);
0170     d->exposureTimeDenEdit->setMinimum(1);
0171     d->exposureTimeDenEdit->setMaximum(100000);
0172     d->exposureTimeDenEdit->setSingleStep(1);
0173     d->exposureTimeDenEdit->setValue(1);
0174     QLabel* const exposureLabel = new QLabel(QLatin1String("/"), this);
0175     exposureLabel->setAlignment (Qt::AlignRight | Qt::AlignVCenter);
0176     d->exposureTimeCheck->setWhatsThis(i18n("Set on this option to set the exposure time "
0177                                             "of picture, given in seconds."));
0178 
0179     // --------------------------------------------------------
0180 
0181     d->exposureProgramCheck = new MetadataCheckBox(i18n("Exposure program:"), this);
0182     d->exposureProgramCB    = new QComboBox(this);
0183     d->exposureProgramCB->insertItem(0, i18nc("exposure program", "Not defined"));
0184     d->exposureProgramCB->insertItem(1, i18nc("exposure program", "Manual"));
0185     d->exposureProgramCB->insertItem(2, i18nc("exposure program", "Auto"));
0186     d->exposureProgramCB->insertItem(3, i18nc("exposure program", "Aperture priority"));
0187     d->exposureProgramCB->insertItem(4, i18nc("exposure program", "Shutter priority"));
0188     d->exposureProgramCB->insertItem(5, i18nc("exposure program", "Creative program"));
0189     d->exposureProgramCB->insertItem(6, i18nc("exposure program", "Action program"));
0190     d->exposureProgramCB->insertItem(7, i18nc("exposure program", "Portrait mode"));
0191     d->exposureProgramCB->insertItem(8, i18nc("exposure program", "Landscape mode"));
0192     d->exposureProgramCB->setWhatsThis(i18n("Select here the program used by the camera "
0193                                             "to set exposure when the picture was taken."));
0194 
0195     // --------------------------------------------------------
0196 
0197     d->exposureModeCheck = new MetadataCheckBox(i18n("Exposure mode:"), this);
0198     d->exposureModeCB    = new QComboBox(this);
0199     d->exposureModeCB->insertItem(0, i18nc("exposure mode", "Auto"));
0200     d->exposureModeCB->insertItem(1, i18nc("exposure mode", "Manual"));
0201     d->exposureModeCB->insertItem(2, i18nc("exposure mode", "Auto bracket"));
0202     d->exposureModeCB->setWhatsThis(i18n("Select here the mode used by the camera "
0203                                          "to set exposure when the picture was taken. "
0204                                          "In auto-bracketing mode, the camera shoots a "
0205                                          "series of frames of the same scene at different "
0206                                          "exposure settings."));
0207 
0208     // --------------------------------------------------------
0209 
0210     d->exposureBiasCheck = new QCheckBox(i18n("Exposure bias (APEX):"), this);
0211     d->exposureBiasEdit  = new QDoubleSpinBox(this);
0212     d->exposureBiasEdit->setRange(-99.99, 99.99);
0213     d->exposureBiasEdit->setSingleStep(0.1);
0214     d->exposureBiasEdit->setValue(0.0);
0215     d->exposureBiasEdit->setWhatsThis(i18n("Set here the exposure bias value (in APEX units) "
0216                                            "used by camera to take the picture."));
0217 
0218     DLineWidget* const line2 = new DLineWidget(Qt::Horizontal, this);
0219 
0220     // --------------------------------------------------------
0221 
0222     d->meteringModeCheck = new MetadataCheckBox(i18n("Metering mode:"), this);
0223     d->meteringModeCB    = new QComboBox(this);
0224     d->meteringModeCB->insertItem(0, i18nc("metering mode", "Unknown"));
0225     d->meteringModeCB->insertItem(1, i18nc("metering mode", "Average"));
0226     d->meteringModeCB->insertItem(2, i18nc("metering mode", "Center weighted average"));
0227     d->meteringModeCB->insertItem(3, i18nc("metering mode", "Spot"));
0228     d->meteringModeCB->insertItem(4, i18nc("metering mode", "Multi-spot"));
0229     d->meteringModeCB->insertItem(5, i18nc("metering mode", "Multi-segment"));
0230     d->meteringModeCB->insertItem(6, i18nc("metering mode", "Partial"));
0231     d->meteringModeCB->insertItem(7, i18nc("metering mode", "Other"));
0232     d->meteringModeCB->setWhatsThis(i18n("Select here the metering mode used by the camera "
0233                                          "to set exposure when the picture was taken."));
0234 
0235     // --------------------------------------------------------
0236 
0237     d->ISOSpeedCheck = new MetadataCheckBox(i18n("Sensitivity (ISO):"), this);
0238     d->ISOSpeedCB    = new QComboBox(this);
0239     d->ISOSpeedCB->insertItem(1, QLatin1String("10"));
0240     d->ISOSpeedCB->insertItem(2, QLatin1String("12"));
0241     d->ISOSpeedCB->insertItem(3, QLatin1String("16"));
0242     d->ISOSpeedCB->insertItem(4, QLatin1String("20"));
0243     d->ISOSpeedCB->insertItem(5, QLatin1String("25"));
0244     d->ISOSpeedCB->insertItem(6, QLatin1String("32"));
0245     d->ISOSpeedCB->insertItem(7, QLatin1String("40"));
0246     d->ISOSpeedCB->insertItem(8, QLatin1String("50"));
0247     d->ISOSpeedCB->insertItem(9, QLatin1String("64"));
0248     d->ISOSpeedCB->insertItem(10, QLatin1String("80"));
0249     d->ISOSpeedCB->insertItem(11, QLatin1String("100"));
0250     d->ISOSpeedCB->insertItem(12, QLatin1String("125"));
0251     d->ISOSpeedCB->insertItem(13, QLatin1String("160"));
0252     d->ISOSpeedCB->insertItem(14, QLatin1String("200"));
0253     d->ISOSpeedCB->insertItem(15, QLatin1String("250"));
0254     d->ISOSpeedCB->insertItem(16, QLatin1String("320"));
0255     d->ISOSpeedCB->insertItem(17, QLatin1String("400"));
0256     d->ISOSpeedCB->insertItem(18, QLatin1String("500"));
0257     d->ISOSpeedCB->insertItem(19, QLatin1String("640"));
0258     d->ISOSpeedCB->insertItem(20, QLatin1String("800"));
0259     d->ISOSpeedCB->insertItem(21, QLatin1String("1000"));
0260     d->ISOSpeedCB->insertItem(22, QLatin1String("1250"));
0261     d->ISOSpeedCB->insertItem(23, QLatin1String("1600"));
0262     d->ISOSpeedCB->insertItem(24, QLatin1String("2000"));
0263     d->ISOSpeedCB->insertItem(25, QLatin1String("2500"));
0264     d->ISOSpeedCB->insertItem(26, QLatin1String("3200"));
0265     d->ISOSpeedCB->insertItem(27, QLatin1String("4000"));
0266     d->ISOSpeedCB->insertItem(28, QLatin1String("5000"));
0267     d->ISOSpeedCB->insertItem(29, QLatin1String("6400"));
0268     d->ISOSpeedCB->insertItem(30, QLatin1String("8000"));
0269     d->ISOSpeedCB->insertItem(31, QLatin1String("10000"));
0270     d->ISOSpeedCB->insertItem(32, QLatin1String("12500"));
0271     d->ISOSpeedCB->insertItem(33, QLatin1String("16000"));
0272     d->ISOSpeedCB->insertItem(34, QLatin1String("20000"));
0273     d->ISOSpeedCB->insertItem(35, QLatin1String("25000"));
0274     d->ISOSpeedCB->insertItem(36, QLatin1String("32000"));
0275     d->ISOSpeedCB->setWhatsThis(i18n("Select here the ISO Speed of the camera "
0276                                      "which took the picture."));
0277 
0278     // --------------------------------------------------------
0279 
0280     d->sensingMethodCheck = new MetadataCheckBox(i18n("Sensing method:"), this);
0281     d->sensingMethodCB    = new QComboBox(this);
0282     d->sensingMethodCB->insertItem(0, i18n("Not defined"));
0283     d->sensingMethodCB->insertItem(1, i18n("One-chip color area"));
0284     d->sensingMethodCB->insertItem(2, i18n("Two-chip color area"));
0285     d->sensingMethodCB->insertItem(3, i18n("Three-chip color area"));
0286     d->sensingMethodCB->insertItem(4, i18n("Color sequential area"));
0287     d->sensingMethodCB->insertItem(5, i18n("Trilinear sensor"));
0288     d->sensingMethodCB->insertItem(6, i18n("Color sequential linear"));
0289     d->sensingMethodCB->setWhatsThis(i18n("Select here the image sensor type used by the camera "
0290                                           "to take the picture."));
0291 
0292     // --------------------------------------------------------
0293 
0294     d->sceneTypeCheck = new MetadataCheckBox(i18nc("@option", "Scene capture type:"), this);
0295     d->sceneTypeCB    = new QComboBox(this);
0296     d->sceneTypeCB->insertItem(0, i18nc("@item: scene type", "Standard"));
0297     d->sceneTypeCB->insertItem(1, i18nc("@item: scene type", "Landscape"));
0298     d->sceneTypeCB->insertItem(2, i18nc("@item: scene type", "Portrait"));
0299     d->sceneTypeCB->insertItem(3, i18nc("@item: scene type", "Night scene"));
0300     d->sceneTypeCB->setWhatsThis(i18nc("@info", "Select here the type of scene used by the camera "
0301                                        "to take the picture."));
0302 
0303     // --------------------------------------------------------
0304 
0305     d->subjectDistanceTypeCheck = new MetadataCheckBox(i18nc("@option", "Subject distance type:"), this);
0306     d->subjectDistanceTypeCB    = new QComboBox(this);
0307     d->subjectDistanceTypeCB->insertItem(1, i18nc("@item: subject distance", "Unknown"));
0308     d->subjectDistanceTypeCB->insertItem(2, i18nc("@item: subject distance", "Macro"));
0309     d->subjectDistanceTypeCB->insertItem(3, i18nc("@item: subject distance", "Close view"));
0310     d->subjectDistanceTypeCB->insertItem(4, i18nc("@item: subject distance", "Distant view"));
0311     d->subjectDistanceTypeCB->setWhatsThis(i18nc("@info", "Select here the type of distance between "
0312                                                  "the subject and the image input equipment."));
0313 
0314     // --------------------------------------------------------
0315 
0316     QLabel* const note = new QLabel(i18n("<b>Note:</b> "
0317                  "<b><a href='https://en.wikipedia.org/wiki/EXIF'>Exif</a></b> "
0318                  "text tags marked by (*) only support printable "
0319                  "<b><a href='https://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
0320                  "characters."), this);
0321     note->setOpenExternalLinks(true);
0322     note->setWordWrap(true);
0323     note->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
0324 
0325     // --------------------------------------------------------
0326 
0327     grid->addWidget(d->makeCheck,                   0, 0, 1, 1);
0328     grid->addWidget(d->makeEdit,                    0, 2, 1, 4);
0329     grid->addWidget(d->modelCheck,                  1, 0, 1, 1);
0330     grid->addWidget(d->modelEdit,                   1, 2, 1, 4);
0331     grid->addWidget(d->deviceTypeCheck,             2, 0, 1, 1);
0332     grid->addWidget(d->deviceTypeCB,                2, 2, 1, 4);
0333     grid->addWidget(warning,                        3, 0, 1, 6);
0334     grid->addWidget(line,                           4, 0, 1, 6);
0335     grid->addWidget(d->exposureTimeCheck,           5, 0, 1, 1);
0336     grid->addWidget(d->exposureTimeNumEdit,         5, 2, 1, 1);
0337     grid->addWidget(exposureLabel,                  5, 3, 1, 1);
0338     grid->addWidget(d->exposureTimeDenEdit,         5, 4, 1, 1);
0339     grid->addWidget(d->exposureProgramCheck,        6, 0, 1, 1);
0340     grid->addWidget(d->exposureProgramCB,           6, 2, 1, 4);
0341     grid->addWidget(d->exposureModeCheck,           7, 0, 1, 1);
0342     grid->addWidget(d->exposureModeCB,              7, 2, 1, 4);
0343     grid->addWidget(d->exposureBiasCheck,           8, 0, 1, 1);
0344     grid->addWidget(d->exposureBiasEdit,            8, 2, 1, 1);
0345     grid->addWidget(line2,                          9, 0, 1, 6);
0346     grid->addWidget(d->meteringModeCheck,          10, 0, 1, 1);
0347     grid->addWidget(d->meteringModeCB,             10, 2, 1, 4);
0348     grid->addWidget(d->ISOSpeedCheck,              11, 0, 1, 1);
0349     grid->addWidget(d->ISOSpeedCB,                 11, 2, 1, 4);
0350     grid->addWidget(d->sensingMethodCheck,         12, 0, 1, 1);
0351     grid->addWidget(d->sensingMethodCB,            12, 2, 1, 4);
0352     grid->addWidget(d->sceneTypeCheck,             13, 0, 1, 1);
0353     grid->addWidget(d->sceneTypeCB,                13, 2, 1, 4);
0354     grid->addWidget(d->subjectDistanceTypeCheck,   14, 0, 1, 1);
0355     grid->addWidget(d->subjectDistanceTypeCB,      14, 2, 1, 4);
0356     grid->addWidget(note, 15, 0, 1, 5+1);
0357     grid->setColumnStretch(1, 10);
0358     grid->setColumnStretch(5, 10);
0359     grid->setRowStretch(16, 10);
0360 
0361     int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0362                        QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0363 
0364     grid->setContentsMargins(spacing, spacing, spacing, spacing);
0365     grid->setSpacing(spacing);
0366 
0367     // --------------------------------------------------------
0368 
0369     connect(d->makeCheck, SIGNAL(toggled(bool)),
0370             d->makeEdit, SLOT(setEnabled(bool)));
0371 
0372     connect(d->modelCheck, SIGNAL(toggled(bool)),
0373             d->modelEdit, SLOT(setEnabled(bool)));
0374 
0375     connect(d->deviceTypeCheck, SIGNAL(toggled(bool)),
0376             d->deviceTypeCB, SLOT(setEnabled(bool)));
0377 
0378     connect(d->exposureTimeCheck, SIGNAL(toggled(bool)),
0379             d->exposureTimeNumEdit, SLOT(setEnabled(bool)));
0380 
0381     connect(d->exposureTimeCheck, SIGNAL(toggled(bool)),
0382             d->exposureTimeDenEdit, SLOT(setEnabled(bool)));
0383 
0384     connect(d->exposureProgramCheck, SIGNAL(toggled(bool)),
0385             d->exposureProgramCB, SLOT(setEnabled(bool)));
0386 
0387     connect(d->exposureModeCheck, SIGNAL(toggled(bool)),
0388             d->exposureModeCB, SLOT(setEnabled(bool)));
0389 
0390     connect(d->exposureBiasCheck, SIGNAL(toggled(bool)),
0391             d->exposureBiasEdit, SLOT(setEnabled(bool)));
0392 
0393     connect(d->meteringModeCheck, SIGNAL(toggled(bool)),
0394             d->meteringModeCB, SLOT(setEnabled(bool)));
0395 
0396     connect(d->ISOSpeedCheck, SIGNAL(toggled(bool)),
0397             d->ISOSpeedCB, SLOT(setEnabled(bool)));
0398 
0399     connect(d->sensingMethodCheck, SIGNAL(toggled(bool)),
0400             d->sensingMethodCB, SLOT(setEnabled(bool)));
0401 
0402     connect(d->sceneTypeCheck, SIGNAL(toggled(bool)),
0403             d->sceneTypeCB, SLOT(setEnabled(bool)));
0404 
0405     connect(d->subjectDistanceTypeCheck, SIGNAL(toggled(bool)),
0406             d->subjectDistanceTypeCB, SLOT(setEnabled(bool)));
0407 
0408     // --------------------------------------------------------
0409 
0410     connect(d->makeCheck, SIGNAL(toggled(bool)),
0411             this, SIGNAL(signalModified()));
0412 
0413     connect(d->modelCheck, SIGNAL(toggled(bool)),
0414             this, SIGNAL(signalModified()));
0415 
0416     connect(d->exposureTimeCheck, SIGNAL(toggled(bool)),
0417             this, SIGNAL(signalModified()));
0418 
0419     connect(d->exposureBiasCheck, SIGNAL(toggled(bool)),
0420             this, SIGNAL(signalModified()));
0421 
0422     connect(d->deviceTypeCheck, SIGNAL(toggled(bool)),
0423             this, SIGNAL(signalModified()));
0424 
0425     connect(d->exposureProgramCheck, SIGNAL(toggled(bool)),
0426             this, SIGNAL(signalModified()));
0427 
0428     connect(d->exposureModeCheck, SIGNAL(toggled(bool)),
0429             this, SIGNAL(signalModified()));
0430 
0431     connect(d->meteringModeCheck, SIGNAL(toggled(bool)),
0432             this, SIGNAL(signalModified()));
0433 
0434     connect(d->ISOSpeedCheck, SIGNAL(toggled(bool)),
0435             this, SIGNAL(signalModified()));
0436 
0437     connect(d->sensingMethodCheck, SIGNAL(toggled(bool)),
0438             this, SIGNAL(signalModified()));
0439 
0440     connect(d->sceneTypeCheck, SIGNAL(toggled(bool)),
0441             this, SIGNAL(signalModified()));
0442 
0443     connect(d->subjectDistanceTypeCheck, SIGNAL(toggled(bool)),
0444             this, SIGNAL(signalModified()));
0445 
0446     // --------------------------------------------------------
0447 
0448     connect(d->deviceTypeCB, SIGNAL(activated(int)),
0449             this, SIGNAL(signalModified()));
0450 
0451     connect(d->exposureProgramCB, SIGNAL(activated(int)),
0452             this, SIGNAL(signalModified()));
0453 
0454     connect(d->exposureModeCB, SIGNAL(activated(int)),
0455             this, SIGNAL(signalModified()));
0456 
0457     connect(d->ISOSpeedCB, SIGNAL(activated(int)),
0458             this, SIGNAL(signalModified()));
0459 
0460     connect(d->meteringModeCB, SIGNAL(activated(int)),
0461             this, SIGNAL(signalModified()));
0462 
0463     connect(d->sensingMethodCB, SIGNAL(activated(int)),
0464             this, SIGNAL(signalModified()));
0465 
0466     connect(d->sceneTypeCB, SIGNAL(activated(int)),
0467             this, SIGNAL(signalModified()));
0468 
0469     connect(d->subjectDistanceTypeCB, SIGNAL(activated(int)),
0470             this, SIGNAL(signalModified()));
0471 
0472     connect(d->makeEdit, SIGNAL(textChanged(QString)),
0473             this, SIGNAL(signalModified()));
0474 
0475     connect(d->modelEdit, SIGNAL(textChanged(QString)),
0476             this, SIGNAL(signalModified()));
0477 
0478     connect(d->exposureTimeNumEdit, SIGNAL(valueChanged(int)),
0479             this, SIGNAL(signalModified()));
0480 
0481     connect(d->exposureTimeDenEdit, SIGNAL(valueChanged(int)),
0482             this, SIGNAL(signalModified()));
0483 
0484     connect(d->exposureBiasEdit, SIGNAL(valueChanged(double)),
0485             this, SIGNAL(signalModified()));
0486 }
0487 
0488 EXIFDevice::~EXIFDevice()
0489 {
0490     delete d;
0491 }
0492 
0493 void EXIFDevice::readMetadata(const DMetadata& meta)
0494 {
0495     blockSignals(true);
0496 
0497     long int num = 1, den = 1;
0498     long     val = 0;
0499     QString  data;
0500 
0501     d->makeEdit->clear();
0502     d->makeCheck->setChecked(false);
0503     data = meta.getExifTagString("Exif.Image.Make", false);
0504 
0505     if (!data.isNull())
0506     {
0507         d->makeEdit->setText(data);
0508         d->makeCheck->setChecked(true);
0509     }
0510 
0511     d->makeEdit->setEnabled(d->makeCheck->isChecked());
0512 
0513     d->modelEdit->clear();
0514     d->modelCheck->setChecked(false);
0515     data = meta.getExifTagString("Exif.Image.Model", false);
0516 
0517     if (!data.isNull())
0518     {
0519         d->modelEdit->setText(data);
0520         d->modelCheck->setChecked(true);
0521     }
0522 
0523     d->modelEdit->setEnabled(d->modelCheck->isChecked());
0524 
0525     d->deviceTypeCB->setCurrentIndex(2);     // DSC
0526     d->deviceTypeCheck->setChecked(false);
0527 
0528     if (meta.getExifTagLong("Exif.Photo.FileSource", val))
0529     {
0530         if ((val > 0) && (val < 4))
0531         {
0532             d->deviceTypeCB->setCurrentIndex(val-1);
0533             d->deviceTypeCheck->setChecked(true);
0534         }
0535         else
0536         {
0537             d->deviceTypeCheck->setValid(false);
0538         }
0539     }
0540 
0541     d->deviceTypeCB->setEnabled(d->deviceTypeCheck->isChecked());
0542 
0543     d->exposureTimeNumEdit->setValue(1);
0544     d->exposureTimeDenEdit->setValue(1);
0545     d->exposureTimeCheck->setChecked(false);
0546 
0547     if (meta.getExifTagRational("Exif.Photo.ExposureTime", num, den))
0548     {
0549         d->exposureTimeNumEdit->setValue(num);
0550         d->exposureTimeDenEdit->setValue(den);
0551         d->exposureTimeCheck->setChecked(true);
0552     }
0553     else if (meta.getExifTagRational("Exif.Photo.ShutterSpeedValue", num, den))
0554     {
0555         double tmp = std::exp(std::log(2.0) * (double)(num) / (double)(den));
0556 
0557         if (tmp > 1.0)
0558             num = (long int)(tmp + 0.5);
0559         else
0560             den = (long int)(1.0 / tmp + 0.5);
0561 
0562         d->exposureTimeNumEdit->setValue(num);
0563         d->exposureTimeDenEdit->setValue(den);
0564         d->exposureTimeCheck->setChecked(true);
0565     }
0566 
0567     d->exposureTimeNumEdit->setEnabled(d->exposureTimeCheck->isChecked());
0568     d->exposureTimeDenEdit->setEnabled(d->exposureTimeCheck->isChecked());
0569 
0570     d->exposureProgramCB->setCurrentIndex(0);
0571     d->exposureProgramCheck->setChecked(false);
0572 
0573     if (meta.getExifTagLong("Exif.Photo.ExposureProgram", val))
0574     {
0575         if ((val >= 0) && (val <= 8))
0576         {
0577             d->exposureProgramCB->setCurrentIndex(val);
0578             d->exposureProgramCheck->setChecked(true);
0579         }
0580         else
0581         {
0582             d->exposureProgramCheck->setValid(false);
0583         }
0584     }
0585 
0586     d->exposureProgramCB->setEnabled(d->exposureProgramCheck->isChecked());
0587 
0588     d->exposureModeCB->setCurrentIndex(0);
0589     d->exposureModeCheck->setChecked(false);
0590 
0591     if (meta.getExifTagLong("Exif.Photo.ExposureMode", val))
0592     {
0593         if ((val >= 0) && (val <= 2))
0594         {
0595             d->exposureModeCB->setCurrentIndex(val);
0596             d->exposureModeCheck->setChecked(true);
0597         }
0598         else
0599         {
0600             d->exposureModeCheck->setValid(false);
0601         }
0602     }
0603 
0604     d->exposureModeCB->setEnabled(d->exposureModeCheck->isChecked());
0605 
0606     d->exposureBiasEdit->setValue(0.0);
0607     d->exposureBiasCheck->setChecked(false);
0608 
0609     if (meta.getExifTagRational("Exif.Photo.ExposureBiasValue", num, den))
0610     {
0611         d->exposureBiasEdit->setValue((double)(num) / (double)(den));
0612         d->exposureBiasCheck->setChecked(true);
0613     }
0614 
0615     d->exposureBiasEdit->setEnabled(d->exposureBiasCheck->isChecked());
0616 
0617     d->meteringModeCB->setCurrentIndex(0);
0618     d->meteringModeCheck->setChecked(false);
0619 
0620     if (meta.getExifTagLong("Exif.Photo.MeteringMode", val))
0621     {
0622         if (((val >= 0) && (val <= 6)) || (val == 255))
0623         {
0624             d->meteringModeCB->setCurrentIndex((val == 255) ? 7 : val);
0625             d->meteringModeCheck->setChecked(true);
0626         }
0627         else
0628         {
0629             d->meteringModeCheck->setValid(false);
0630         }
0631     }
0632 
0633     d->meteringModeCB->setEnabled(d->meteringModeCheck->isChecked());
0634 
0635     d->ISOSpeedCB->setCurrentIndex(10);       // 100 ISO
0636     d->ISOSpeedCheck->setChecked(false);
0637 
0638     if (meta.getExifTagLong("Exif.Photo.ISOSpeedRatings", val))
0639     {
0640         int item = -1;
0641 
0642         for (int i = 0 ; i < d->ISOSpeedCB->count() ; ++i)
0643         {
0644             if (d->ISOSpeedCB->itemText(i) == QString::number(val))
0645             {
0646                 item = i;
0647             }
0648         }
0649 
0650         if (item != -1)
0651         {
0652             d->ISOSpeedCB->setCurrentIndex(item);
0653             d->ISOSpeedCheck->setChecked(true);
0654         }
0655         else
0656         {
0657             d->ISOSpeedCheck->setValid(false);
0658         }
0659     }
0660     else if (meta.getExifTagRational("Exif.Photo.ExposureIndex", num, den))
0661     {
0662         val      = num / den;
0663         int item = -1;
0664 
0665         for (int i = 0 ; i < d->ISOSpeedCB->count() ; ++i)
0666         {
0667             if (d->ISOSpeedCB->itemText(i) == QString::number(val))
0668             {
0669                 item = i;
0670             }
0671         }
0672 
0673         if (item != -1)
0674         {
0675             d->ISOSpeedCB->setCurrentIndex(item);
0676             d->ISOSpeedCheck->setChecked(true);
0677         }
0678         else
0679         {
0680             d->ISOSpeedCheck->setValid(false);
0681         }
0682     }
0683 
0684     d->ISOSpeedCB->setEnabled(d->ISOSpeedCheck->isChecked());
0685 
0686     d->sensingMethodCB->setCurrentIndex(0);
0687     d->sensingMethodCheck->setChecked(false);
0688 
0689     if (meta.getExifTagLong("Exif.Photo.SensingMethod", val))
0690     {
0691         if ((val >= 1) && (val <= 8) && (val != 6))
0692         {
0693             d->sensingMethodCB->setCurrentIndex((val > 6) ? val-2 : val-1);
0694             d->sensingMethodCheck->setChecked(true);
0695         }
0696         else
0697         {
0698             d->sensingMethodCheck->setValid(false);
0699         }
0700     }
0701 
0702     d->sensingMethodCB->setEnabled(d->sensingMethodCheck->isChecked());
0703 
0704     d->sceneTypeCB->setCurrentIndex(0);
0705     d->sceneTypeCheck->setChecked(false);
0706 
0707     if (meta.getExifTagLong("Exif.Photo.SceneCaptureType", val))
0708     {
0709         if ((val >= 0) && (val <= 3))
0710         {
0711             d->sceneTypeCB->setCurrentIndex(val);
0712             d->sceneTypeCheck->setChecked(true);
0713         }
0714         else
0715         {
0716             d->sceneTypeCheck->setValid(false);
0717         }
0718     }
0719 
0720     d->sceneTypeCB->setEnabled(d->sceneTypeCheck->isChecked());
0721 
0722     d->subjectDistanceTypeCB->setCurrentIndex(0);
0723     d->subjectDistanceTypeCheck->setChecked(false);
0724 
0725     if (meta.getExifTagLong("Exif.Photo.SubjectDistanceRange", val))
0726     {
0727         if ((val >= 0) && (val <= 3))
0728         {
0729             d->subjectDistanceTypeCB->setCurrentIndex(val);
0730             d->subjectDistanceTypeCheck->setChecked(true);
0731         }
0732         else
0733         {
0734             d->subjectDistanceTypeCheck->setValid(false);
0735         }
0736     }
0737 
0738     d->subjectDistanceTypeCB->setEnabled(d->subjectDistanceTypeCheck->isChecked());
0739 
0740     blockSignals(false);
0741 }
0742 
0743 void EXIFDevice::applyMetadata(const DMetadata& meta)
0744 {
0745     long int num = 1, den = 1;
0746 
0747     if (d->makeCheck->isChecked())
0748         meta.setExifTagString("Exif.Image.Make", d->makeEdit->text());
0749     else
0750         meta.removeExifTag("Exif.Image.Make");
0751 
0752     if (d->modelCheck->isChecked())
0753         meta.setExifTagString("Exif.Image.Model", d->modelEdit->text());
0754     else
0755         meta.removeExifTag("Exif.Image.Model");
0756 
0757     if (d->deviceTypeCheck->isChecked())
0758         meta.setExifTagLong("Exif.Photo.FileSource", d->deviceTypeCB->currentIndex()+1);
0759     else if (d->deviceTypeCheck->isValid())
0760         meta.removeExifTag("Exif.Photo.FileSource");
0761 
0762     if (d->exposureTimeCheck->isChecked())
0763     {
0764         meta.setExifTagRational("Exif.Photo.ExposureTime", d->exposureTimeNumEdit->value(),
0765                                                            d->exposureTimeDenEdit->value());
0766 
0767         double exposureTime = (double)(d->exposureTimeNumEdit->value()) /
0768                               (double)(d->exposureTimeDenEdit->value());
0769         double shutterSpeed = (-1.0) * (std::log(exposureTime) / std::log(2.0));
0770         meta.convertToRational(shutterSpeed, &num, &den, 8);
0771         meta.setExifTagRational("Exif.Photo.ShutterSpeedValue", num, den);
0772     }
0773     else
0774     {
0775         meta.removeExifTag("Exif.Photo.ExposureTime");
0776         meta.removeExifTag("Exif.Photo.ShutterSpeedValue");
0777     }
0778 
0779     if      (d->exposureProgramCheck->isChecked())
0780         meta.setExifTagLong("Exif.Photo.ExposureProgram", d->exposureProgramCB->currentIndex());
0781     else if (d->exposureProgramCheck->isValid())
0782         meta.removeExifTag("Exif.Photo.ExposureProgram");
0783 
0784     if      (d->exposureModeCheck->isChecked())
0785         meta.setExifTagLong("Exif.Photo.ExposureMode", d->exposureModeCB->currentIndex());
0786     else if (d->exposureModeCheck->isValid())
0787         meta.removeExifTag("Exif.Photo.ExposureMode");
0788 
0789     if (d->exposureBiasCheck->isChecked())
0790     {
0791         meta.convertToRational(d->exposureBiasEdit->value(), &num, &den, 1);
0792         meta.setExifTagRational("Exif.Photo.ExposureBiasValue", num, den);
0793     }
0794     else
0795     {
0796         meta.removeExifTag("Exif.Photo.ExposureBiasValue");
0797     }
0798 
0799     if      (d->meteringModeCheck->isChecked())
0800     {
0801         long met = d->meteringModeCB->currentIndex();
0802         meta.setExifTagLong("Exif.Photo.MeteringMode", (met > 6) ? 255 : met);
0803     }
0804     else if (d->meteringModeCheck->isValid())
0805         meta.removeExifTag("Exif.Photo.MeteringMode");
0806 
0807     if      (d->ISOSpeedCheck->isChecked())
0808     {
0809         meta.setExifTagLong("Exif.Photo.ISOSpeedRatings", d->ISOSpeedCB->currentText().toLong());
0810 
0811         meta.convertToRational(d->ISOSpeedCB->currentText().toDouble(), &num, &den, 1);
0812         meta.setExifTagRational("Exif.Photo.ExposureIndex", num, den);
0813     }
0814     else if (d->ISOSpeedCheck->isValid())
0815     {
0816         meta.removeExifTag("Exif.Photo.ISOSpeedRatings");
0817         meta.removeExifTag("Exif.Photo.ExposureIndex");
0818     }
0819 
0820     if      (d->sensingMethodCheck->isChecked())
0821     {
0822         long sem = d->sensingMethodCB->currentIndex();
0823         meta.setExifTagLong("Exif.Photo.SensingMethod", sem > 4 ? sem+2 : sem+1);
0824     }
0825     else if (d->sensingMethodCheck->isValid())
0826     {
0827         meta.removeExifTag("Exif.Photo.SensingMethod");
0828     }
0829 
0830     if      (d->sceneTypeCheck->isChecked())
0831         meta.setExifTagLong("Exif.Photo.SceneCaptureType", d->sceneTypeCB->currentIndex());
0832     else if (d->sceneTypeCheck->isValid())
0833         meta.removeExifTag("Exif.Photo.SceneCaptureType");
0834 
0835     if      (d->subjectDistanceTypeCheck->isChecked())
0836         meta.setExifTagLong("Exif.Photo.SubjectDistanceRange", d->subjectDistanceTypeCB->currentIndex());
0837     else if (d->subjectDistanceTypeCheck->isValid())
0838         meta.removeExifTag("Exif.Photo.SubjectDistanceRange");
0839 }
0840 
0841 } // namespace DigikamGenericMetadataEditPlugin
0842 
0843 #include "moc_exifdevice.cpp"