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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2006-10-15
0007  * Description : IPTC keywords 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 "iptckeywords.h"
0016 
0017 // Qt includes
0018 
0019 #include <QCheckBox>
0020 #include <QLabel>
0021 #include <QPushButton>
0022 #include <QGridLayout>
0023 #include <QApplication>
0024 #include <QStyle>
0025 #include <QListWidget>
0026 #include <QToolTip>
0027 
0028 // KDE includes
0029 
0030 #include <klocalizedstring.h>
0031 
0032 // Local includes
0033 
0034 #include "dtextedit.h"
0035 
0036 namespace DigikamGenericMetadataEditPlugin
0037 {
0038 
0039 class Q_DECL_HIDDEN IPTCKeywords::Private
0040 {
0041 public:
0042 
0043     explicit Private()
0044       : addKeywordButton(nullptr),
0045         delKeywordButton(nullptr),
0046         repKeywordButton(nullptr),
0047         keywordsCheck   (nullptr),
0048         keywordsEdit    (nullptr),
0049         keywordsBox     (nullptr)
0050     {
0051     }
0052 
0053     QStringList      oldKeywords;
0054 
0055     QPushButton*     addKeywordButton;
0056     QPushButton*     delKeywordButton;
0057     QPushButton*     repKeywordButton;
0058 
0059     QCheckBox*       keywordsCheck;
0060 
0061     DPlainTextEdit* keywordsEdit;
0062 
0063     QListWidget*     keywordsBox;
0064 };
0065 
0066 IPTCKeywords::IPTCKeywords(QWidget* const parent)
0067     : MetadataEditPage(parent),
0068       d               (new Private)
0069 {
0070     QGridLayout* const grid = new QGridLayout(widget());
0071 
0072     // --------------------------------------------------------
0073 
0074     d->keywordsCheck  = new QCheckBox(i18n("Use information retrieval words:"), this);
0075 
0076     d->keywordsEdit   = new DPlainTextEdit(this);
0077     d->keywordsEdit->setMaxLength(64);
0078     d->keywordsEdit->setLinesVisible(1);
0079     d->keywordsEdit->setPlaceholderText(i18n("Set here a keyword"));
0080     d->keywordsEdit->setWhatsThis(i18n("Enter here a new keyword. "
0081                                       "This field is limited to 64 characters."));
0082 
0083     d->keywordsBox    = new QListWidget(this);
0084     d->keywordsBox->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
0085 
0086     d->addKeywordButton = new QPushButton( i18n("&Add"), this);
0087     d->delKeywordButton = new QPushButton( i18n("&Delete"), this);
0088     d->repKeywordButton = new QPushButton( i18n("&Replace"), this);
0089     d->addKeywordButton->setIcon(QIcon::fromTheme(QLatin1String("list-add")));
0090     d->delKeywordButton->setIcon(QIcon::fromTheme(QLatin1String("edit-delete")));
0091     d->repKeywordButton->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
0092     d->delKeywordButton->setEnabled(false);
0093     d->repKeywordButton->setEnabled(false);
0094 
0095     // --------------------------------------------------------
0096 
0097     QLabel* const note = new QLabel(i18n("<b>Note: "
0098                  "<a href='https://en.wikipedia.org/wiki/IPTC_Information_Interchange_Model'>IPTC</a> "
0099                  "text tags are limited string sizes. Use contextual help for details. "
0100                  "Consider to use <a href='https://en.wikipedia.org/wiki/Extensible_Metadata_Platform'>XMP</a> instead.</b>"),
0101                  this);
0102     note->setMaximumWidth(150);
0103     note->setOpenExternalLinks(true);
0104     note->setWordWrap(true);
0105     note->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
0106 
0107     // --------------------------------------------------------
0108 
0109     grid->setAlignment(Qt::AlignTop);
0110     grid->addWidget(d->keywordsCheck,       0, 0, 1, 2);
0111     grid->addWidget(d->keywordsEdit,        1, 0, 1, 1);
0112     grid->addWidget(d->keywordsBox,         2, 0, 5, 1);
0113     grid->addWidget(d->addKeywordButton,    2, 1, 1, 1);
0114     grid->addWidget(d->delKeywordButton,    3, 1, 1, 1);
0115     grid->addWidget(d->repKeywordButton,    4, 1, 1, 1);
0116     grid->addWidget(note,                   5, 1, 1, 1);
0117     grid->setColumnStretch(0, 10);
0118     grid->setRowStretch(6, 10);
0119 
0120     int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0121                        QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0122 
0123     grid->setContentsMargins(spacing, spacing, spacing, spacing);
0124     grid->setSpacing(spacing);
0125 
0126     // --------------------------------------------------------
0127 
0128     connect(d->keywordsBox, SIGNAL(itemSelectionChanged()),
0129             this, SLOT(slotKeywordSelectionChanged()));
0130 
0131     connect(d->addKeywordButton, SIGNAL(clicked()),
0132             this, SLOT(slotAddKeyword()));
0133 
0134     connect(d->delKeywordButton, SIGNAL(clicked()),
0135             this, SLOT(slotDelKeyword()));
0136 
0137     connect(d->repKeywordButton, SIGNAL(clicked()),
0138             this, SLOT(slotRepKeyword()));
0139 
0140     // --------------------------------------------------------
0141 
0142     connect(d->keywordsCheck, SIGNAL(toggled(bool)),
0143             d->keywordsEdit, SLOT(setEnabled(bool)));
0144 
0145     connect(d->keywordsCheck, SIGNAL(toggled(bool)),
0146             d->addKeywordButton, SLOT(setEnabled(bool)));
0147 
0148     connect(d->keywordsCheck, SIGNAL(toggled(bool)),
0149             d->delKeywordButton, SLOT(setEnabled(bool)));
0150 
0151     connect(d->keywordsCheck, SIGNAL(toggled(bool)),
0152             d->repKeywordButton, SLOT(setEnabled(bool)));
0153 
0154     connect(d->keywordsCheck, SIGNAL(toggled(bool)),
0155             d->keywordsBox, SLOT(setEnabled(bool)));
0156 
0157     // --------------------------------------------------------
0158 
0159     connect(d->keywordsCheck, SIGNAL(toggled(bool)),
0160             this, SIGNAL(signalModified()));
0161 
0162     connect(d->addKeywordButton, SIGNAL(clicked()),
0163             this, SIGNAL(signalModified()));
0164 
0165     connect(d->delKeywordButton, SIGNAL(clicked()),
0166             this, SIGNAL(signalModified()));
0167 
0168     connect(d->repKeywordButton, SIGNAL(clicked()),
0169             this, SIGNAL(signalModified()));
0170 }
0171 
0172 IPTCKeywords::~IPTCKeywords()
0173 {
0174     delete d;
0175 }
0176 
0177 void IPTCKeywords::slotDelKeyword()
0178 {
0179     QListWidgetItem* const item = d->keywordsBox->currentItem();
0180 
0181     if (!item)
0182     {
0183         return;
0184     }
0185 
0186     d->keywordsBox->takeItem(d->keywordsBox->row(item));
0187     delete item;
0188 }
0189 
0190 void IPTCKeywords::slotRepKeyword()
0191 {
0192     QString newKeyword = d->keywordsEdit->text();
0193 
0194     if (newKeyword.isEmpty())
0195     {
0196         return;
0197     }
0198 
0199     if (!d->keywordsBox->selectedItems().isEmpty())
0200     {
0201         d->keywordsBox->selectedItems()[0]->setText(newKeyword);
0202         d->keywordsEdit->clear();
0203     }
0204 }
0205 
0206 void IPTCKeywords::slotKeywordSelectionChanged()
0207 {
0208     if (!d->keywordsBox->selectedItems().isEmpty())
0209     {
0210         d->keywordsEdit->setText(d->keywordsBox->selectedItems()[0]->text());
0211         d->delKeywordButton->setEnabled(true);
0212         d->repKeywordButton->setEnabled(true);
0213     }
0214     else
0215     {
0216         d->delKeywordButton->setEnabled(false);
0217         d->repKeywordButton->setEnabled(false);
0218     }
0219 }
0220 
0221 void IPTCKeywords::slotAddKeyword()
0222 {
0223     QString newKeyword = d->keywordsEdit->text();
0224 
0225     if (newKeyword.isEmpty())
0226     {
0227         return;
0228     }
0229 
0230     bool found = false;
0231 
0232     for (int i = 0 ; i < d->keywordsBox->count(); ++i)
0233     {
0234         QListWidgetItem* const item = d->keywordsBox->item(i);
0235 
0236         if (newKeyword == item->text())
0237         {
0238             found = true;
0239             break;
0240         }
0241     }
0242 
0243     if (!found)
0244     {
0245         d->keywordsBox->insertItem(d->keywordsBox->count(), newKeyword);
0246         d->keywordsEdit->clear();
0247     }
0248 }
0249 
0250 void IPTCKeywords::readMetadata(const DMetadata& meta)
0251 {
0252     blockSignals(true);
0253 
0254     d->oldKeywords = meta.getIptcKeywords();
0255 
0256     d->keywordsBox->clear();
0257     d->keywordsCheck->setChecked(false);
0258 
0259     if (!d->oldKeywords.isEmpty())
0260     {
0261         d->keywordsBox->insertItems(0, d->oldKeywords);
0262         d->keywordsCheck->setChecked(true);
0263     }
0264 
0265     d->keywordsEdit->setEnabled(d->keywordsCheck->isChecked());
0266     d->keywordsBox->setEnabled(d->keywordsCheck->isChecked());
0267     d->addKeywordButton->setEnabled(d->keywordsCheck->isChecked());
0268     d->delKeywordButton->setEnabled(d->keywordsCheck->isChecked());
0269 
0270     blockSignals(false);
0271 }
0272 
0273 void IPTCKeywords::applyMetadata(const DMetadata& meta)
0274 {
0275     QStringList newKeywords;
0276 
0277     for (int i = 0 ; i < d->keywordsBox->count(); ++i)
0278     {
0279         QListWidgetItem* const item = d->keywordsBox->item(i);
0280         newKeywords.append(item->text());
0281     }
0282 
0283     if (d->keywordsCheck->isChecked())
0284         meta.setIptcKeywords(d->oldKeywords, newKeywords);
0285     else
0286         meta.setIptcKeywords(d->oldKeywords, QStringList());
0287 }
0288 
0289 } // namespace DigikamGenericMetadataEditPlugin
0290 
0291 #include "moc_iptckeywords.cpp"