File indexing completed on 2025-01-19 03:51:21
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2006-10-12 0007 * Description : EXIF caption 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 "exifcaption.h" 0016 0017 // Qt includes 0018 0019 #include <QIcon> 0020 #include <QStyle> 0021 #include <QCheckBox> 0022 #include <QGridLayout> 0023 #include <QApplication> 0024 0025 // KDE includes 0026 0027 #include <klocalizedstring.h> 0028 0029 // Local includes 0030 0031 #include "dtextedit.h" 0032 0033 namespace DigikamGenericMetadataEditPlugin 0034 { 0035 0036 class Q_DECL_HIDDEN EXIFCaption::Private 0037 { 0038 public: 0039 0040 explicit Private() 0041 : documentNameCheck (nullptr), 0042 imageDescCheck (nullptr), 0043 artistCheck (nullptr), 0044 copyrightCheck (nullptr), 0045 userCommentCheck (nullptr), 0046 syncJFIFCommentCheck (nullptr), 0047 syncXMPCaptionCheck (nullptr), 0048 syncIPTCCaptionCheck (nullptr), 0049 userCommentEdit (nullptr), 0050 documentNameEdit (nullptr), 0051 imageDescEdit (nullptr), 0052 artistEdit (nullptr), 0053 copyrightEdit (nullptr), 0054 documentNameIcon (nullptr), 0055 imageDescIcon (nullptr), 0056 artistIcon (nullptr), 0057 copyrightIcon (nullptr) 0058 { 0059 } 0060 0061 QCheckBox* documentNameCheck; 0062 QCheckBox* imageDescCheck; 0063 QCheckBox* artistCheck; 0064 QCheckBox* copyrightCheck; 0065 QCheckBox* userCommentCheck; 0066 QCheckBox* syncJFIFCommentCheck; 0067 QCheckBox* syncXMPCaptionCheck; 0068 QCheckBox* syncIPTCCaptionCheck; 0069 0070 DPlainTextEdit* userCommentEdit; 0071 0072 DTextEdit* documentNameEdit; 0073 DTextEdit* imageDescEdit; 0074 DTextEdit* artistEdit; 0075 DTextEdit* copyrightEdit; 0076 0077 QLabel* documentNameIcon; 0078 QLabel* imageDescIcon; 0079 QLabel* artistIcon; 0080 QLabel* copyrightIcon; 0081 }; 0082 0083 EXIFCaption::EXIFCaption(QWidget* const parent) 0084 : MetadataEditPage(parent), 0085 d (new Private) 0086 { 0087 QGridLayout* const grid = new QGridLayout(widget()); 0088 0089 QString asciiPrint; // List of printable ASCII characters. 0090 0091 for (int i = 32 ; i <= 127 ; ++i) 0092 { 0093 asciiPrint.append(QChar(i)); 0094 } 0095 0096 // -------------------------------------------------------- 0097 0098 d->documentNameCheck = new QCheckBox(i18nc("name of the document this image has been scanned from", "Name (*):"), this); 0099 d->documentNameEdit = new DTextEdit(this); 0100 d->documentNameEdit->setAcceptedCharacters(asciiPrint); 0101 d->documentNameEdit->setPlaceholderText(i18n("Set here the original document name.")); 0102 d->documentNameEdit->setWhatsThis(i18n("Enter the name of the document from which " 0103 "this image was been scanned. This field is limited " 0104 "to ASCII characters.")); 0105 0106 // -------------------------------------------------------- 0107 0108 d->imageDescCheck = new QCheckBox(i18nc("image description", "Description (*):"), this); 0109 d->imageDescEdit = new DTextEdit(this); 0110 d->imageDescEdit->setAcceptedCharacters(asciiPrint); 0111 d->imageDescEdit->setPlaceholderText(i18n("Set here the image description.")); 0112 d->imageDescEdit->setWhatsThis(i18n("Enter the image description. This field is limited " 0113 "to ASCII characters.")); 0114 0115 // -------------------------------------------------------- 0116 0117 d->artistCheck = new QCheckBox(i18n("Artist (*):"), this); 0118 d->artistEdit = new DTextEdit(this); 0119 d->artistEdit->setAcceptedCharacters(asciiPrint); 0120 d->artistEdit->setPlaceholderText(i18n("Set here the author's name.")); 0121 d->artistEdit->setWhatsThis(i18n("Enter the image author's name separated by semi-colons. " 0122 "This field is limited to ASCII characters.")); 0123 0124 // -------------------------------------------------------- 0125 0126 d->copyrightCheck = new QCheckBox(i18n("Copyright (*):"), this); 0127 d->copyrightEdit = new DTextEdit(this); 0128 d->copyrightEdit->setAcceptedCharacters(asciiPrint); 0129 d->copyrightEdit->setPlaceholderText(i18n("Set here the copyright owner.")); 0130 d->copyrightEdit->setWhatsThis(i18n("Enter the copyright owner of the image. " 0131 "This field is limited to ASCII characters.")); 0132 0133 // -------------------------------------------------------- 0134 0135 d->userCommentCheck = new QCheckBox(i18nc("image caption", "Caption:"), this); 0136 d->userCommentEdit = new DPlainTextEdit(this); 0137 d->userCommentEdit->setLinesVisible(4); 0138 d->userCommentEdit->setPlaceholderText(i18n("Set here the image's caption.")); 0139 d->userCommentEdit->setWhatsThis(i18n("Enter the image's caption. " 0140 "This field is not limited. UTF8 encoding " 0141 "will be used to save the text.")); 0142 0143 d->syncJFIFCommentCheck = new QCheckBox(i18n("Sync JFIF Comment section"), this); 0144 d->syncXMPCaptionCheck = new QCheckBox(i18n("Sync XMP caption"), this); 0145 d->syncIPTCCaptionCheck = new QCheckBox(i18n("Sync IPTC caption (warning: limited to 2000 characters)"), this); 0146 0147 if (!DMetadata::supportXmp()) 0148 d->syncXMPCaptionCheck->setEnabled(false); 0149 0150 // -------------------------------------------------------- 0151 0152 QLabel* const note = new QLabel(i18n("<b>Note:</b> " 0153 "<b><a href='https://en.wikipedia.org/wiki/EXIF'>Exif</a></b> " 0154 "text tags marked by (*) only support printable " 0155 "<b><a href='https://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> " 0156 "characters."), this); 0157 note->setOpenExternalLinks(true); 0158 note->setWordWrap(true); 0159 note->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); 0160 0161 // -------------------------------------------------------- 0162 0163 grid->addWidget(d->documentNameCheck, 0, 0, 1, 1); 0164 grid->addWidget(d->documentNameEdit, 1, 0, 1, 1); 0165 grid->addWidget(d->imageDescCheck, 2, 0, 1, 1); 0166 grid->addWidget(d->imageDescEdit, 3, 0, 1, 1); 0167 grid->addWidget(d->artistCheck, 4, 0, 1, 1); 0168 grid->addWidget(d->artistEdit, 5, 0, 1, 1); 0169 grid->addWidget(d->copyrightCheck, 6, 0, 1, 1); 0170 grid->addWidget(d->copyrightEdit, 7, 0, 1, 1); 0171 grid->addWidget(d->userCommentCheck, 8, 0, 1, 1); 0172 grid->addWidget(d->userCommentEdit, 9, 0, 1, 1); 0173 grid->addWidget(d->syncJFIFCommentCheck, 10, 0, 1, 1); 0174 grid->addWidget(d->syncXMPCaptionCheck, 11, 0, 1, 1); 0175 grid->addWidget(d->syncIPTCCaptionCheck, 12, 0, 1, 1); 0176 grid->addWidget(note, 13, 0, 1, 1); 0177 grid->setRowStretch(14, 10); 0178 grid->setColumnStretch(0, 10); 0179 0180 int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0181 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)); 0182 0183 grid->setContentsMargins(spacing, spacing, spacing, spacing); 0184 grid->setSpacing(spacing); 0185 0186 // -------------------------------------------------------- 0187 0188 connect(d->documentNameCheck, SIGNAL(toggled(bool)), 0189 d->documentNameEdit, SLOT(setEnabled(bool))); 0190 0191 connect(d->imageDescCheck, SIGNAL(toggled(bool)), 0192 d->imageDescEdit, SLOT(setEnabled(bool))); 0193 0194 connect(d->artistCheck, SIGNAL(toggled(bool)), 0195 d->artistEdit, SLOT(setEnabled(bool))); 0196 0197 connect(d->copyrightCheck, SIGNAL(toggled(bool)), 0198 d->copyrightEdit, SLOT(setEnabled(bool))); 0199 0200 connect(d->userCommentCheck, SIGNAL(toggled(bool)), 0201 d->userCommentEdit, SLOT(setEnabled(bool))); 0202 0203 connect(d->userCommentCheck, SIGNAL(toggled(bool)), 0204 d->syncJFIFCommentCheck, SLOT(setEnabled(bool))); 0205 0206 connect(d->userCommentCheck, SIGNAL(toggled(bool)), 0207 d->syncXMPCaptionCheck, SLOT(setEnabled(bool))); 0208 0209 connect(d->userCommentCheck, SIGNAL(toggled(bool)), 0210 d->syncIPTCCaptionCheck, SLOT(setEnabled(bool))); 0211 0212 // -------------------------------------------------------- 0213 0214 connect(d->documentNameCheck, SIGNAL(toggled(bool)), 0215 this, SIGNAL(signalModified())); 0216 0217 connect(d->imageDescCheck, SIGNAL(toggled(bool)), 0218 this, SIGNAL(signalModified())); 0219 0220 connect(d->artistCheck, SIGNAL(toggled(bool)), 0221 this, SIGNAL(signalModified())); 0222 0223 connect(d->copyrightCheck, SIGNAL(toggled(bool)), 0224 this, SIGNAL(signalModified())); 0225 0226 connect(d->userCommentCheck, SIGNAL(toggled(bool)), 0227 this, SIGNAL(signalModified())); 0228 0229 // -------------------------------------------------------- 0230 0231 connect(d->userCommentEdit, SIGNAL(textChanged()), 0232 this, SIGNAL(signalModified())); 0233 0234 connect(d->documentNameEdit, SIGNAL(textChanged()), 0235 this, SIGNAL(signalModified())); 0236 0237 connect(d->imageDescEdit, SIGNAL(textChanged()), 0238 this, SIGNAL(signalModified())); 0239 0240 connect(d->artistEdit, SIGNAL(textChanged()), 0241 this, SIGNAL(signalModified())); 0242 0243 connect(d->copyrightEdit, SIGNAL(textChanged()), 0244 this, SIGNAL(signalModified())); 0245 } 0246 0247 EXIFCaption::~EXIFCaption() 0248 { 0249 delete d; 0250 } 0251 0252 bool EXIFCaption::syncJFIFCommentIsChecked() const 0253 { 0254 return d->syncJFIFCommentCheck->isChecked(); 0255 } 0256 0257 bool EXIFCaption::syncXMPCaptionIsChecked() const 0258 { 0259 return d->syncXMPCaptionCheck->isChecked(); 0260 } 0261 0262 bool EXIFCaption::syncIPTCCaptionIsChecked() const 0263 { 0264 return d->syncIPTCCaptionCheck->isChecked(); 0265 } 0266 0267 QString EXIFCaption::getEXIFUserComments() const 0268 { 0269 return d->userCommentEdit->toPlainText(); 0270 } 0271 0272 void EXIFCaption::setCheckedSyncJFIFComment(bool c) 0273 { 0274 d->syncJFIFCommentCheck->setChecked(c); 0275 } 0276 0277 void EXIFCaption::setCheckedSyncXMPCaption(bool c) 0278 { 0279 d->syncXMPCaptionCheck->setChecked(c); 0280 } 0281 0282 void EXIFCaption::setCheckedSyncIPTCCaption(bool c) 0283 { 0284 d->syncIPTCCaptionCheck->setChecked(c); 0285 } 0286 0287 void EXIFCaption::readMetadata(const DMetadata& meta) 0288 { 0289 blockSignals(true); 0290 0291 QString data; 0292 0293 d->documentNameEdit->clear(); 0294 d->documentNameCheck->setChecked(false); 0295 data = meta.getExifTagString("Exif.Image.DocumentName", false); 0296 0297 if (!data.isNull()) 0298 { 0299 d->documentNameEdit->setText(data); 0300 d->documentNameCheck->setChecked(true); 0301 } 0302 0303 d->documentNameEdit->setEnabled(d->documentNameCheck->isChecked()); 0304 0305 d->imageDescEdit->clear(); 0306 d->imageDescCheck->setChecked(false); 0307 data = meta.getExifTagString("Exif.Image.ImageDescription", false); 0308 0309 if (!data.isNull()) 0310 { 0311 d->imageDescEdit->setText(data); 0312 d->imageDescCheck->setChecked(true); 0313 } 0314 0315 d->imageDescEdit->setEnabled(d->imageDescCheck->isChecked()); 0316 0317 d->artistEdit->clear(); 0318 d->artistCheck->setChecked(false); 0319 data = meta.getExifTagString("Exif.Image.Artist", false); 0320 0321 if (!data.isNull()) 0322 { 0323 d->artistEdit->setText(data); 0324 d->artistCheck->setChecked(true); 0325 } 0326 0327 d->artistEdit->setEnabled(d->artistCheck->isChecked()); 0328 0329 d->copyrightEdit->clear(); 0330 d->copyrightCheck->setChecked(false); 0331 data = meta.getExifTagString("Exif.Image.Copyright", false); 0332 0333 if (!data.isNull()) 0334 { 0335 d->copyrightEdit->setText(data); 0336 d->copyrightCheck->setChecked(true); 0337 } 0338 0339 d->copyrightEdit->setEnabled(d->copyrightCheck->isChecked()); 0340 0341 d->userCommentEdit->clear(); 0342 d->userCommentCheck->setChecked(false); 0343 data = meta.getExifComment(false); 0344 0345 if (!data.isNull()) 0346 { 0347 d->userCommentEdit->setPlainText(data); 0348 d->userCommentCheck->setChecked(true); 0349 } 0350 0351 d->userCommentEdit->setEnabled(d->userCommentCheck->isChecked()); 0352 d->syncJFIFCommentCheck->setEnabled(d->userCommentCheck->isChecked()); 0353 d->syncXMPCaptionCheck->setEnabled(d->userCommentCheck->isChecked()); 0354 d->syncIPTCCaptionCheck->setEnabled(d->userCommentCheck->isChecked()); 0355 0356 blockSignals(false); 0357 } 0358 0359 void EXIFCaption::applyMetadata(const DMetadata& meta) 0360 { 0361 if (d->documentNameCheck->isChecked()) 0362 meta.setExifTagString("Exif.Image.DocumentName", d->documentNameEdit->text()); 0363 else 0364 meta.removeExifTag("Exif.Image.DocumentName"); 0365 0366 if (d->imageDescCheck->isChecked()) 0367 meta.setExifTagString("Exif.Image.ImageDescription", d->imageDescEdit->text()); 0368 else 0369 meta.removeExifTag("Exif.Image.ImageDescription"); 0370 0371 if (d->artistCheck->isChecked()) 0372 meta.setExifTagString("Exif.Image.Artist", d->artistEdit->text()); 0373 else 0374 meta.removeExifTag("Exif.Image.Artist"); 0375 0376 if (d->copyrightCheck->isChecked()) 0377 meta.setExifTagString("Exif.Image.Copyright", d->copyrightEdit->text()); 0378 else 0379 meta.removeExifTag("Exif.Image.Copyright"); 0380 0381 if (d->userCommentCheck->isChecked()) 0382 { 0383 meta.setExifComment(d->userCommentEdit->toPlainText(), false); 0384 0385 if (syncJFIFCommentIsChecked()) 0386 meta.setComments(d->userCommentEdit->toPlainText().toUtf8()); 0387 0388 if (meta.supportXmp() && syncXMPCaptionIsChecked()) 0389 { 0390 meta.setXmpTagStringLangAlt("Xmp.dc.description", 0391 d->userCommentEdit->toPlainText(), 0392 QString()); 0393 0394 meta.setXmpTagStringLangAlt("Xmp.exif.UserComment", 0395 d->userCommentEdit->toPlainText(), 0396 QString()); 0397 } 0398 0399 if (syncIPTCCaptionIsChecked()) 0400 meta.setIptcTagString("Iptc.Application2.Caption", d->userCommentEdit->toPlainText()); 0401 } 0402 else 0403 meta.removeExifTag("Exif.Photo.UserComment"); 0404 } 0405 0406 } // namespace DigikamGenericMetadataEditPlugin 0407 0408 #include "moc_exifcaption.cpp"