File indexing completed on 2024-04-28 04:21:03
0001 // SPDX-FileCopyrightText: 2003 - 2020 The KPhotoAlbum Development Team 0002 // SPDX-FileCopyrightText: 2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0003 // SPDX-FileCopyrightText: 2023 Alexander Lohnau <alexander.lohnau@gmx.de> 0004 // 0005 // SPDX-License-Identifier: GPL-2.0-or-later 0006 0007 #include "SearchDialog.h" 0008 0009 #include <kpaexif/Database.h> 0010 0011 #include <KConfigGroup> 0012 #include <KLocalizedString> 0013 #include <QDialogButtonBox> 0014 #include <QGridLayout> 0015 #include <QGroupBox> 0016 #include <QHBoxLayout> 0017 #include <QPushButton> 0018 #include <QScrollArea> 0019 #include <QVBoxLayout> 0020 #include <qcheckbox.h> 0021 #include <qlabel.h> 0022 #include <qlayout.h> 0023 #include <qspinbox.h> 0024 0025 using namespace Exif; 0026 0027 Exif::SearchDialog::SearchDialog(const Database *exifDB, QWidget *parent) 0028 : KPageDialog(parent) 0029 , m_exifDB(exifDB) 0030 { 0031 setWindowTitle(i18nc("@title:window", "Exif Search")); 0032 setFaceType(Tabbed); 0033 0034 QWidget *settings = new QWidget; 0035 KPageWidgetItem *page = new KPageWidgetItem(settings, i18n("Settings")); 0036 0037 addPage(page); 0038 QVBoxLayout *vlay = new QVBoxLayout(settings); 0039 0040 // Iso, Exposure, FNumber 0041 QHBoxLayout *hlay = new QHBoxLayout; 0042 vlay->addLayout(hlay); 0043 QGridLayout *gridLayout = new QGridLayout; 0044 gridLayout->setSpacing(6); 0045 hlay->addLayout(gridLayout); 0046 hlay->addStretch(1); 0047 0048 makeISO(gridLayout); 0049 makeExposureTime(gridLayout); 0050 hlay->addSpacing(30); 0051 0052 gridLayout = new QGridLayout; 0053 gridLayout->setSpacing(6); 0054 hlay->addLayout(gridLayout); 0055 hlay->addStretch(1); 0056 m_fNumber = makeFNumber(i18n("Aperture (F Number)"), QString::fromLatin1("Exif_Photo_FNumber"), gridLayout, 1); 0057 0058 hlay->addSpacing(30); 0059 0060 // Focal length 0061 QHBoxLayout *focalLayout = new QHBoxLayout; 0062 focalLayout->setSpacing(6); 0063 hlay->addLayout(focalLayout); 0064 hlay->addStretch(1); 0065 0066 QLabel *label = new QLabel(i18n("Focal Length")); 0067 focalLayout->addWidget(label); 0068 0069 m_fromFocalLength = new QSpinBox; 0070 focalLayout->addWidget(m_fromFocalLength); 0071 m_fromFocalLength->setRange(0, 10000); 0072 m_fromFocalLength->setSingleStep(10); 0073 0074 label = new QLabel(i18nc("As in 'A range from x to y'", "to")); 0075 focalLayout->addWidget(label); 0076 0077 m_toFocalLength = new QSpinBox; 0078 focalLayout->addWidget(m_toFocalLength); 0079 m_toFocalLength->setRange(0, 10000); 0080 m_toFocalLength->setSingleStep(10); 0081 0082 m_toFocalLength->setValue(10000); 0083 QString suffix = i18nc("This is millimeter for focal length, like 35mm", "mm"); 0084 m_fromFocalLength->setSuffix(suffix); 0085 m_toFocalLength->setSuffix(suffix); 0086 0087 connect(m_fromFocalLength, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SearchDialog::fromFocalLengthChanged); 0088 connect(m_toFocalLength, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SearchDialog::toFocalLengthChanged); 0089 0090 // exposure program and Metring mode 0091 hlay = new QHBoxLayout; 0092 vlay->addLayout(hlay); 0093 hlay->addWidget(makeExposureProgram(settings)); 0094 hlay->addWidget(makeMeteringMode(settings)); 0095 0096 vlay->addStretch(1); 0097 0098 // ------------------------------------------------------------ Camera 0099 page = new KPageWidgetItem(makeCamera(), i18n("Camera")); 0100 addPage(page); 0101 0102 // ------------------------------------------------------------ Lens 0103 page = new KPageWidgetItem(makeLens(), i18n("Lens")); 0104 addPage(page); 0105 0106 // ------------------------------------------------------------ Misc 0107 QWidget *misc = new QWidget; 0108 addPage(new KPageWidgetItem(misc, i18n("Miscellaneous"))); 0109 vlay = new QVBoxLayout(misc); 0110 vlay->addWidget(makeOrientation(misc), 1); 0111 0112 hlay = new QHBoxLayout; 0113 vlay->addLayout(hlay); 0114 hlay->addWidget(makeContrast(misc)); 0115 hlay->addWidget(makeSharpness(misc)); 0116 hlay->addWidget(makeSaturation(misc)); 0117 vlay->addStretch(1); 0118 } 0119 0120 void Exif::SearchDialog::makeISO(QGridLayout *layout) 0121 { 0122 Exif::RangeWidget::ValueList list; 0123 list << Exif::RangeWidget::Value(100, QString::fromLatin1("100")) 0124 << Exif::RangeWidget::Value(200, QString::fromLatin1("200")) 0125 << Exif::RangeWidget::Value(400, QString::fromLatin1("400")) 0126 << Exif::RangeWidget::Value(800, QString::fromLatin1("800")) 0127 << Exif::RangeWidget::Value(1600, QString::fromLatin1("1600")) 0128 << Exif::RangeWidget::Value(3200, QString::fromLatin1("3200")) 0129 << Exif::RangeWidget::Value(6400, QString::fromLatin1("6400")) 0130 << Exif::RangeWidget::Value(12800, QString::fromLatin1("12800")) 0131 << Exif::RangeWidget::Value(25600, QString::fromLatin1("25600")) 0132 << Exif::RangeWidget::Value(51200, QString::fromLatin1("51200")); 0133 0134 m_iso = new RangeWidget(i18n("Iso setting"), QString::fromLatin1("Exif_Photo_ISOSpeedRatings"), list, layout, 0, this); 0135 } 0136 0137 void Exif::SearchDialog::makeExposureTime(QGridLayout *layout) 0138 { 0139 QString secs = i18nc("Example 1.6 secs (as in seconds)", "secs."); 0140 Exif::RangeWidget::ValueList list; 0141 list 0142 << Exif::RangeWidget::Value(1.0 / 4000, QString::fromLatin1("1/4000")) 0143 << Exif::RangeWidget::Value(1.0 / 3200, QString::fromLatin1("1/3200")) 0144 << Exif::RangeWidget::Value(1.0 / 2500, QString::fromLatin1("1/2500")) 0145 << Exif::RangeWidget::Value(1.0 / 2000, QString::fromLatin1("1/2000")) 0146 << Exif::RangeWidget::Value(1.0 / 1600, QString::fromLatin1("1/1600")) 0147 << Exif::RangeWidget::Value(1.0 / 1250, QString::fromLatin1("1/1250")) 0148 << Exif::RangeWidget::Value(1.0 / 1000, QString::fromLatin1("1/1000")) 0149 << Exif::RangeWidget::Value(1.0 / 800, QString::fromLatin1("1/800")) 0150 << Exif::RangeWidget::Value(1.0 / 640, QString::fromLatin1("1/640")) 0151 << Exif::RangeWidget::Value(1.0 / 500, QString::fromLatin1("1/500")) 0152 << Exif::RangeWidget::Value(1.0 / 400, QString::fromLatin1("1/400")) 0153 << Exif::RangeWidget::Value(1.0 / 320, QString::fromLatin1("1/320")) 0154 << Exif::RangeWidget::Value(1.0 / 250, QString::fromLatin1("1/250")) 0155 << Exif::RangeWidget::Value(1.0 / 200, QString::fromLatin1("1/200")) 0156 << Exif::RangeWidget::Value(1.0 / 160, QString::fromLatin1("1/160")) 0157 << Exif::RangeWidget::Value(1.0 / 125, QString::fromLatin1("1/125")) 0158 << Exif::RangeWidget::Value(1.0 / 100, QString::fromLatin1("1/100")) 0159 << Exif::RangeWidget::Value(1.0 / 80, QString::fromLatin1("1/80")) 0160 << Exif::RangeWidget::Value(1.0 / 60, QString::fromLatin1("1/60")) 0161 << Exif::RangeWidget::Value(1.0 / 50, QString::fromLatin1("1/50")) 0162 << Exif::RangeWidget::Value(1.0 / 40, QString::fromLatin1("1/40")) 0163 << Exif::RangeWidget::Value(1.0 / 30, QString::fromLatin1("1/30")) 0164 << Exif::RangeWidget::Value(1.0 / 25, QString::fromLatin1("1/25")) 0165 << Exif::RangeWidget::Value(1.0 / 20, QString::fromLatin1("1/20")) 0166 << Exif::RangeWidget::Value(1.0 / 15, QString::fromLatin1("1/15")) 0167 << Exif::RangeWidget::Value(1.0 / 13, QString::fromLatin1("1/13")) 0168 << Exif::RangeWidget::Value(1.0 / 10, QString::fromLatin1("1/10")) 0169 << Exif::RangeWidget::Value(1.0 / 8, QString::fromLatin1("1/8")) 0170 << Exif::RangeWidget::Value(1.0 / 6, QString::fromLatin1("1/6")) 0171 << Exif::RangeWidget::Value(1.0 / 5, QString::fromLatin1("1/5")) 0172 << Exif::RangeWidget::Value(1.0 / 4, QString::fromLatin1("1/4")) 0173 << Exif::RangeWidget::Value(0.3, QString::fromLatin1("0.3 %1").arg(secs)) 0174 << Exif::RangeWidget::Value(0.4, QString::fromLatin1("0.4 %1").arg(secs)) 0175 << Exif::RangeWidget::Value(0.5, QString::fromLatin1("0.5 %1").arg(secs)) 0176 << Exif::RangeWidget::Value(0.6, QString::fromLatin1("0.6 %1").arg(secs)) 0177 << Exif::RangeWidget::Value(0.8, QString::fromLatin1("0.8 %1").arg(secs)) 0178 << Exif::RangeWidget::Value(1, i18n("1 second")) 0179 << Exif::RangeWidget::Value(1.3, QString::fromLatin1("1.3 %1").arg(secs)) 0180 << Exif::RangeWidget::Value(1.6, QString::fromLatin1("1.6 %1").arg(secs)) 0181 << Exif::RangeWidget::Value(2, QString::fromLatin1("2 %1").arg(secs)) 0182 << Exif::RangeWidget::Value(2.5, QString::fromLatin1("2.5 %1").arg(secs)) 0183 << Exif::RangeWidget::Value(3.2, QString::fromLatin1("3.2 %1").arg(secs)) 0184 << Exif::RangeWidget::Value(4, QString::fromLatin1("4 %1").arg(secs)) 0185 << Exif::RangeWidget::Value(5, QString::fromLatin1("5 %1").arg(secs)) 0186 << Exif::RangeWidget::Value(6, QString::fromLatin1("6 %1").arg(secs)) 0187 << Exif::RangeWidget::Value(8, QString::fromLatin1("8 %1").arg(secs)) 0188 << Exif::RangeWidget::Value(10, QString::fromLatin1("10 %1").arg(secs)) 0189 << Exif::RangeWidget::Value(13, QString::fromLatin1("13 %1").arg(secs)) 0190 << Exif::RangeWidget::Value(15, QString::fromLatin1("15 %1").arg(secs)) 0191 << Exif::RangeWidget::Value(20, QString::fromLatin1("20 %1").arg(secs)) 0192 << Exif::RangeWidget::Value(25, QString::fromLatin1("25 %1").arg(secs)) 0193 << Exif::RangeWidget::Value(30, QString::fromLatin1("30 %1").arg(secs)); 0194 0195 m_exposureTime = new RangeWidget(i18n("Exposure time"), QString::fromLatin1("Exif_Photo_ExposureTime"), list, layout, 1, this); 0196 } 0197 0198 RangeWidget *Exif::SearchDialog::makeFNumber(const QString &text, const QString &key, QGridLayout *layout, int row) 0199 { 0200 Exif::RangeWidget::ValueList list; 0201 list 0202 << Exif::RangeWidget::Value(1.4, QString::fromLatin1("1.4")) 0203 << Exif::RangeWidget::Value(1.8, QString::fromLatin1("1.8")) 0204 << Exif::RangeWidget::Value(2.0, QString::fromLatin1("2.0")) 0205 << Exif::RangeWidget::Value(2.2, QString::fromLatin1("2.2")) 0206 << Exif::RangeWidget::Value(2.5, QString::fromLatin1("2.5")) 0207 << Exif::RangeWidget::Value(2.8, QString::fromLatin1("2.8")) 0208 << Exif::RangeWidget::Value(3.2, QString::fromLatin1("3.2")) 0209 << Exif::RangeWidget::Value(3.5, QString::fromLatin1("3.5")) 0210 << Exif::RangeWidget::Value(4.0, QString::fromLatin1("4.0")) 0211 << Exif::RangeWidget::Value(4.5, QString::fromLatin1("4.5")) 0212 << Exif::RangeWidget::Value(5.0, QString::fromLatin1("5.0")) 0213 << Exif::RangeWidget::Value(5.6, QString::fromLatin1("5.6")) 0214 << Exif::RangeWidget::Value(6.3, QString::fromLatin1("6.3")) 0215 << Exif::RangeWidget::Value(7.1, QString::fromLatin1("7.1")) 0216 << Exif::RangeWidget::Value(8.0, QString::fromLatin1("8.0")) 0217 << Exif::RangeWidget::Value(9.0, QString::fromLatin1("9.0")) 0218 << Exif::RangeWidget::Value(10, QString::fromLatin1("10")) 0219 << Exif::RangeWidget::Value(11, QString::fromLatin1("11")) 0220 << Exif::RangeWidget::Value(13, QString::fromLatin1("13")) 0221 << Exif::RangeWidget::Value(14, QString::fromLatin1("14")) 0222 << Exif::RangeWidget::Value(16, QString::fromLatin1("16")) 0223 << Exif::RangeWidget::Value(18, QString::fromLatin1("18")) 0224 << Exif::RangeWidget::Value(20, QString::fromLatin1("20")) 0225 << Exif::RangeWidget::Value(22, QString::fromLatin1("22")) 0226 << Exif::RangeWidget::Value(25, QString::fromLatin1("25")) 0227 << Exif::RangeWidget::Value(29, QString::fromLatin1("29")) 0228 << Exif::RangeWidget::Value(32, QString::fromLatin1("32")) 0229 << Exif::RangeWidget::Value(36, QString::fromLatin1("36")) 0230 << Exif::RangeWidget::Value(40, QString::fromLatin1("40")) 0231 << Exif::RangeWidget::Value(45, QString::fromLatin1("45")); 0232 0233 return new RangeWidget(text, key, list, layout, row, this); 0234 } 0235 0236 #define addSetting(settings, text, num) \ 0237 { \ 0238 QCheckBox *cb = new QCheckBox(i18n(text), box); \ 0239 settings.append(Setting<int>(cb, num)); \ 0240 layout->addWidget(cb); \ 0241 } 0242 0243 QWidget *Exif::SearchDialog::makeExposureProgram(QWidget *parent) 0244 { 0245 QGroupBox *box = new QGroupBox(i18n("Exposure Program"), parent); 0246 QVBoxLayout *layout = new QVBoxLayout(box); 0247 0248 addSetting(m_exposureProgram, "Not defined", 0); 0249 addSetting(m_exposureProgram, "Manual", 1); 0250 addSetting(m_exposureProgram, "Normal program", 2); 0251 addSetting(m_exposureProgram, "Aperture priority", 3); 0252 addSetting(m_exposureProgram, "Shutter priority", 4); 0253 addSetting(m_exposureProgram, "Creative program (biased toward depth of field)", 5); 0254 addSetting(m_exposureProgram, "Action program (biased toward fast shutter speed)", 6); 0255 addSetting(m_exposureProgram, "Portrait mode (for closeup photos with the background out of focus)", 7); 0256 addSetting(m_exposureProgram, "Landscape mode (for landscape photos with the background in focus)", 8); 0257 return box; 0258 } 0259 0260 QWidget *Exif::SearchDialog::makeOrientation(QWidget *parent) 0261 { 0262 QGroupBox *box = new QGroupBox(i18n("Orientation"), parent); 0263 QVBoxLayout *layout = new QVBoxLayout(box); 0264 0265 addSetting(m_orientation, "Not rotated", 0); 0266 addSetting(m_orientation, "Rotated counterclockwise", 6); 0267 addSetting(m_orientation, "Rotated clockwise", 8); 0268 addSetting(m_orientation, "Rotated 180 degrees", 3); 0269 return box; 0270 } 0271 0272 QWidget *Exif::SearchDialog::makeMeteringMode(QWidget *parent) 0273 { 0274 QGroupBox *box = new QGroupBox(i18n("Metering Mode"), parent); 0275 QVBoxLayout *layout = new QVBoxLayout(box); 0276 0277 addSetting(m_meteringMode, "Unknown", 0); 0278 addSetting(m_meteringMode, "Average", 1); 0279 addSetting(m_meteringMode, "CenterWeightedAverage", 2); 0280 addSetting(m_meteringMode, "Spot", 3); 0281 addSetting(m_meteringMode, "MultiSpot", 4); 0282 addSetting(m_meteringMode, "Pattern", 5); 0283 addSetting(m_meteringMode, "Partial", 6); 0284 addSetting(m_meteringMode, "Other", 255); 0285 return box; 0286 } 0287 0288 QWidget *Exif::SearchDialog::makeContrast(QWidget *parent) 0289 { 0290 QGroupBox *box = new QGroupBox(i18n("Contrast"), parent); 0291 QVBoxLayout *layout = new QVBoxLayout(box); 0292 0293 addSetting(m_contrast, "Normal", 0); 0294 addSetting(m_contrast, "Soft", 1); 0295 addSetting(m_contrast, "Hard", 2); 0296 return box; 0297 } 0298 0299 QWidget *Exif::SearchDialog::makeSharpness(QWidget *parent) 0300 { 0301 QGroupBox *box = new QGroupBox(i18n("Sharpness"), parent); 0302 QVBoxLayout *layout = new QVBoxLayout(box); 0303 0304 addSetting(m_sharpness, "Normal", 0); 0305 addSetting(m_sharpness, "Soft", 1); 0306 addSetting(m_sharpness, "Hard", 2); 0307 return box; 0308 } 0309 0310 QWidget *Exif::SearchDialog::makeSaturation(QWidget *parent) 0311 { 0312 QGroupBox *box = new QGroupBox(i18n("Saturation"), parent); 0313 QVBoxLayout *layout = new QVBoxLayout(box); 0314 0315 addSetting(m_saturation, "Normal", 0); 0316 addSetting(m_saturation, "Low", 1); 0317 addSetting(m_saturation, "High", 2); 0318 return box; 0319 } 0320 0321 Exif::SearchInfo Exif::SearchDialog::info() 0322 { 0323 Exif::SearchInfo result(m_exifDB); 0324 result.addSearchKey(QString::fromLatin1("Exif_Photo_MeteringMode"), m_meteringMode.selected()); 0325 result.addSearchKey(QString::fromLatin1("Exif_Photo_ExposureProgram"), m_exposureProgram.selected()); 0326 result.addSearchKey(QString::fromLatin1("Exif_Image_Orientation"), m_orientation.selected()); 0327 result.addSearchKey(QString::fromLatin1("Exif_Photo_MeteringMode"), m_meteringMode.selected()); 0328 result.addSearchKey(QString::fromLatin1("Exif_Photo_Contrast"), m_contrast.selected()); 0329 result.addSearchKey(QString::fromLatin1("Exif_Photo_Sharpness"), m_sharpness.selected()); 0330 result.addSearchKey(QString::fromLatin1("Exif_Photo_Saturation"), m_saturation.selected()); 0331 result.addCamera(m_cameras.selected()); 0332 result.addLens(m_lenses.selected()); 0333 result.addRangeKey(m_iso->range()); 0334 result.addRangeKey(m_exposureTime->range()); 0335 result.addRangeKey(m_fNumber->range()); 0336 0337 SearchInfo::Range focalRange(QString::fromLatin1("Exif_Photo_FocalLength")); 0338 focalRange.min = m_fromFocalLength->value(); 0339 focalRange.max = m_toFocalLength->value(); 0340 result.addRangeKey(focalRange); 0341 return result; 0342 } 0343 0344 QWidget *Exif::SearchDialog::makeCamera() 0345 { 0346 QScrollArea *view = new QScrollArea; 0347 view->setWidgetResizable(true); 0348 0349 QWidget *w = new QWidget; 0350 view->setWidget(w); 0351 QVBoxLayout *layout = new QVBoxLayout(w); 0352 0353 QList<QPair<QString, QString>> cameras = m_exifDB->cameras(); 0354 std::sort(cameras.begin(), cameras.end()); 0355 0356 for (QList<QPair<QString, QString>>::ConstIterator cameraIt = cameras.constBegin(); cameraIt != cameras.constEnd(); ++cameraIt) { 0357 QCheckBox *cb = new QCheckBox(QString::fromUtf8("%1 - %2").arg((*cameraIt).first.trimmed(), (*cameraIt).second.trimmed())); 0358 layout->addWidget(cb); 0359 m_cameras.append(Setting<QPair<QString, QString>>(cb, *cameraIt)); 0360 } 0361 0362 if (cameras.isEmpty()) { 0363 QLabel *label = new QLabel(i18n("No cameras found in the database")); 0364 layout->addWidget(label); 0365 } 0366 0367 return view; 0368 } 0369 0370 QWidget *Exif::SearchDialog::makeLens() 0371 { 0372 QScrollArea *view = new QScrollArea; 0373 view->setWidgetResizable(true); 0374 0375 QWidget *w = new QWidget; 0376 view->setWidget(w); 0377 QVBoxLayout *layout = new QVBoxLayout(w); 0378 0379 QList<QString> lenses = m_exifDB->lenses(); 0380 std::sort(lenses.begin(), lenses.end()); 0381 0382 if (lenses.isEmpty()) { 0383 QLabel *label = new QLabel(i18n("No lenses found in the database")); 0384 layout->addWidget(label); 0385 } else { 0386 // add option "None" first 0387 lenses.prepend(i18nc("As in No persons, no locations etc.", "None")); 0388 0389 for (QList<QString>::ConstIterator lensIt = lenses.constBegin(); lensIt != lenses.constEnd(); ++lensIt) { 0390 QCheckBox *cb = new QCheckBox(QString::fromUtf8("%1").arg((*lensIt).trimmed())); 0391 layout->addWidget(cb); 0392 m_lenses.append(Setting<QString>(cb, *lensIt)); 0393 } 0394 } 0395 0396 if (m_exifDB->DBFileVersionGuaranteed() < 3) { 0397 QLabel *label = new QLabel( 0398 i18n("Not all images in the database have lens information. " 0399 "<note>Recreate the Exif search database to ensure lens data for all images.</note>")); 0400 layout->addWidget(label); 0401 } 0402 0403 return view; 0404 } 0405 0406 void Exif::SearchDialog::fromFocalLengthChanged(int val) 0407 { 0408 if (m_toFocalLength->value() < val) 0409 m_toFocalLength->setValue(val); 0410 } 0411 0412 void Exif::SearchDialog::toFocalLengthChanged(int val) 0413 { 0414 if (m_fromFocalLength->value() > val) 0415 m_fromFocalLength->setValue(val); 0416 } 0417 0418 // vi:expandtab:tabstop=4 shiftwidth=4: 0419 0420 #include "moc_SearchDialog.cpp"