File indexing completed on 2025-12-07 04:08:36

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 subjects editor.
0008  *
0009  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2009-2012 by Andi Clemens <andi dot clemens at googlemail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "subjectwidget.h"
0017 
0018 // Qt includes
0019 
0020 #include <QStandardPaths>
0021 #include <QFile>
0022 #include <QValidator>
0023 #include <QGridLayout>
0024 #include <QPushButton>
0025 #include <QRadioButton>
0026 #include <QButtonGroup>
0027 #include <QListWidget>
0028 #include <QDomDocument>
0029 #include <QDomElement>
0030 #include <QApplication>
0031 #include <QComboBox>
0032 
0033 // KDE includes
0034 
0035 #include <klocalizedstring.h>
0036 
0037 // Local includes
0038 
0039 #include "digikam_debug.h"
0040 
0041 namespace Digikam
0042 {
0043 
0044 class Q_DECL_HIDDEN SubjectWidget::Private
0045 {
0046 public:
0047 
0048     enum EditionMode
0049     {
0050         STANDARD = 0,
0051         CUSTOM
0052     };
0053 
0054 public:
0055 
0056     explicit Private()
0057       : optionsBox      (nullptr),
0058         addSubjectButton(nullptr),
0059         delSubjectButton(nullptr),
0060         repSubjectButton(nullptr),
0061         iprLabel        (nullptr),
0062         refLabel        (nullptr),
0063         nameLabel       (nullptr),
0064         matterLabel     (nullptr),
0065         detailLabel     (nullptr),
0066         btnGroup        (nullptr),
0067         stdBtn          (nullptr),
0068         customBtn       (nullptr),
0069         refCB           (nullptr),
0070         subjectsBox     (nullptr)
0071     {
0072     }
0073 
0074     typedef QMap<QString, SubjectData> SubjectCodesMap;
0075 
0076     SubjectCodesMap                    subMap;
0077 
0078     QStringList                        subjectsList;
0079 
0080     QWidget*                           optionsBox;
0081 
0082     QPushButton*                       addSubjectButton;
0083     QPushButton*                       delSubjectButton;
0084     QPushButton*                       repSubjectButton;
0085 
0086     QLabel*                            iprLabel;
0087     QLabel*                            refLabel;
0088     QLabel*                            nameLabel;
0089     QLabel*                            matterLabel;
0090     QLabel*                            detailLabel;
0091 
0092     QButtonGroup*                      btnGroup;
0093 
0094     QRadioButton*                      stdBtn;
0095     QRadioButton*                      customBtn;
0096 
0097     QComboBox*                         refCB;
0098 
0099     QListWidget*                       subjectsBox;
0100 };
0101 
0102 // --------------------------------------------------------------------------------
0103 
0104 SubjectWidget::SubjectWidget(QWidget* const parent, bool sizeLimited)
0105     : QScrollArea(parent),
0106       d          (new Private)
0107 {
0108     QWidget* const panel   = new QWidget(viewport());
0109     setWidget(panel);
0110     setWidgetResizable(true);
0111 
0112     // Load subject codes provided by IPTC/NAA as xml file.
0113     // See iptc.cms.apa.at/std/topicset/topicset.iptc-subjectcode.xml for details.
0114 
0115     QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
0116                                           QLatin1String("digikam/metadata/topicset.iptc-subjectcode.xml"));
0117 
0118     // NOTE: use dynamic binding as this virtual method can be re-implemented in derived classes.
0119 
0120     if (!this->loadSubjectCodesFromXML(QUrl::fromLocalFile(path)))
0121     {
0122         qCDebug(DIGIKAM_WIDGETS_LOG) << "Cannot load IPTC/NAA subject codes XML database";
0123     }
0124 
0125     // --------------------------------------------------------
0126 
0127     // Subject Reference Number only accept digit.
0128 
0129     QRegularExpression refDigitRx(QLatin1String("^[0-9]{8}$"));
0130     QValidator* const refValidator = new QRegularExpressionValidator(refDigitRx, this);
0131 
0132     // --------------------------------------------------------
0133 
0134     m_subjectsCheck        = new QCheckBox(i18nc("@title: subject widget", "Use structured definition of the subject matter:"), this);
0135     d->optionsBox          = new QWidget;
0136     d->btnGroup            = new QButtonGroup(this);
0137     d->stdBtn              = new QRadioButton;
0138     d->customBtn           = new QRadioButton;
0139     d->refCB               = new QComboBox;
0140     QLabel* const codeLink = new QLabel(QString::fromUtf8("%1 <b><a href='https://www.iptc.org/site/NewsCodes'>%2</a></b>")
0141                                         .arg(i18nc("@label: subject widget", "Use standard"))
0142                                         .arg(i18nc("@label: subject widget", "reference code")));
0143     codeLink->setOpenExternalLinks(true);
0144     codeLink->setWordWrap(false);
0145 
0146     // By default, check box is not visible.
0147 
0148     m_subjectsCheck->setVisible(false);
0149     m_subjectsCheck->setEnabled(false);
0150 
0151     QLabel* const customLabel = new QLabel(i18nc("@label: subject widget", "Use custom definition"));
0152 
0153     d->btnGroup->addButton(d->stdBtn,    Private::STANDARD);
0154     d->btnGroup->addButton(d->customBtn, Private::CUSTOM);
0155     d->btnGroup->setExclusive(true);
0156     d->stdBtn->setChecked(true);
0157 
0158     for (Private::SubjectCodesMap::Iterator it = d->subMap.begin() ; it != d->subMap.end() ; ++it)
0159     {
0160         d->refCB->addItem(it.key());
0161     }
0162 
0163     // --------------------------------------------------------
0164 
0165     m_iprEdit = new QLineEdit;
0166     m_iprEdit->setClearButtonEnabled(true);
0167     m_iprEdit->setPlaceholderText(i18nc("@info", "Set here the Informative Provider Reference"));
0168 
0169     if (sizeLimited)
0170     {
0171         m_iprEdit->setMaxLength(32);
0172     }
0173 
0174     // --------------------------------------------------------
0175 
0176     m_refEdit = new QLineEdit;
0177     m_refEdit->setClearButtonEnabled(true);
0178     m_refEdit->setValidator(refValidator);
0179     m_refEdit->setPlaceholderText(i18nc("@info", "Set here the Subject Reference Number"));
0180 
0181     if (sizeLimited)
0182     {
0183         m_refEdit->setMaxLength(8);
0184     }
0185 
0186     // --------------------------------------------------------
0187 
0188     m_nameEdit = new DTextEdit;
0189     m_nameEdit->setLinesVisible(1);
0190     m_nameEdit->setPlaceholderText(i18nc("@info", "Set here the Subject Name"));
0191 
0192     if (sizeLimited)
0193     {
0194         m_nameEdit->setMaxLength(64);
0195     }
0196 
0197     // --------------------------------------------------------
0198 
0199     m_matterEdit = new DTextEdit;
0200     m_matterEdit->setLinesVisible(1);
0201     m_matterEdit->setPlaceholderText(i18nc("@info", "Set here the Subject Matter Name"));
0202 
0203     if (sizeLimited)
0204     {
0205         m_matterEdit->setMaxLength(64);
0206     }
0207 
0208     // --------------------------------------------------------
0209 
0210     m_detailEdit = new DTextEdit;
0211     m_detailEdit->setLinesVisible(1);
0212     m_detailEdit->setPlaceholderText(i18nc("@info", "Set here the Subject Detail Name"));
0213 
0214     if (sizeLimited)
0215     {
0216         m_detailEdit->setMaxLength(64);
0217     }
0218 
0219     // --------------------------------------------------------
0220 
0221     d->iprLabel    = new QLabel(i18nc("@label: Information Provider Reference: "
0222                                       "A name, registered with the IPTC/NAA, "
0223                                       "identifying the provider that guarantees "
0224                                       "the uniqueness of the UNO", "I.P.R:"));
0225     d->refLabel    = new QLabel(i18nc("@label: subject properties", "Reference:"));
0226     d->nameLabel   = new QLabel(i18nc("@label: subject properties", "Name:"));
0227     d->matterLabel = new QLabel(i18nc("@label: subject properties", "Matter:"));
0228     d->detailLabel = new QLabel(i18nc("@label: subject properties", "Detail:"));
0229 
0230     // --------------------------------------------------------
0231 
0232     d->subjectsBox = new QListWidget;
0233     d->subjectsBox->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
0234 
0235     d->addSubjectButton = new QPushButton(i18nc("@action: subject properties", "&Add"));
0236     d->delSubjectButton = new QPushButton(i18nc("@action: subject properties", "&Delete"));
0237     d->repSubjectButton = new QPushButton(i18nc("@action: subject properties", "&Replace"));
0238     d->addSubjectButton->setIcon(QIcon::fromTheme(QLatin1String("list-add")).pixmap(16, 16));
0239     d->delSubjectButton->setIcon(QIcon::fromTheme(QLatin1String("edit-delete")).pixmap(16, 16));
0240     d->repSubjectButton->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")).pixmap(16, 16));
0241     d->delSubjectButton->setEnabled(false);
0242     d->repSubjectButton->setEnabled(false);
0243 
0244     // --------------------------------------------------------
0245 
0246     m_note = new QLabel;
0247     m_note->setMaximumWidth(150);
0248     m_note->setOpenExternalLinks(true);
0249     m_note->setWordWrap(true);
0250     m_note->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
0251 
0252     // --------------------------------------------------------
0253 
0254     QGridLayout* const optionsBoxLayout = new QGridLayout;
0255     optionsBoxLayout->addWidget(d->stdBtn,      0, 0, 1, 1);
0256     optionsBoxLayout->addWidget(codeLink,       0, 1, 1, 2);
0257     optionsBoxLayout->addWidget(d->refCB,       0, 3, 1, 1);
0258     optionsBoxLayout->addWidget(d->customBtn,   1, 0, 1, 4);
0259     optionsBoxLayout->addWidget(customLabel,    1, 1, 1, 4);
0260     optionsBoxLayout->addWidget(d->iprLabel,    2, 0, 1, 1);
0261     optionsBoxLayout->addWidget(m_iprEdit,      2, 1, 1, 4);
0262     optionsBoxLayout->addWidget(d->refLabel,    3, 0, 1, 1);
0263     optionsBoxLayout->addWidget(m_refEdit,      3, 1, 1, 1);
0264     optionsBoxLayout->addWidget(d->nameLabel,   4, 0, 1, 1);
0265     optionsBoxLayout->addWidget(m_nameEdit,     4, 1, 1, 4);
0266     optionsBoxLayout->addWidget(d->matterLabel, 5, 0, 1, 1);
0267     optionsBoxLayout->addWidget(m_matterEdit,   5, 1, 1, 4);
0268     optionsBoxLayout->addWidget(d->detailLabel, 6, 0, 1, 1);
0269     optionsBoxLayout->addWidget(m_detailEdit,   6, 1, 1, 4);
0270     optionsBoxLayout->setColumnStretch(4, 10);
0271     optionsBoxLayout->setContentsMargins(QMargins());
0272     optionsBoxLayout->setSpacing(qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0273                                       QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)));
0274     d->optionsBox->setLayout(optionsBoxLayout);
0275 
0276     // --------------------------------------------------------
0277 
0278     QGridLayout* const mainLayout = new QGridLayout(widget());
0279     mainLayout->setAlignment(Qt::AlignTop);
0280     mainLayout->addWidget(m_subjectsCheck,     0, 0, 1, 4);
0281     mainLayout->addWidget(d->optionsBox,       1, 0, 1, 4);
0282     mainLayout->addWidget(d->subjectsBox,      2, 0, 5, 3);
0283     mainLayout->addWidget(d->addSubjectButton, 2, 3, 1, 1);
0284     mainLayout->addWidget(d->delSubjectButton, 3, 3, 1, 1);
0285     mainLayout->addWidget(d->repSubjectButton, 4, 3, 1, 1);
0286     mainLayout->addWidget(m_note,              5, 3, 1, 1);
0287     mainLayout->setRowStretch(6, 10);
0288     mainLayout->setColumnStretch(2, 1);
0289 
0290     int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0291                        QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0292 
0293     mainLayout->setContentsMargins(spacing, spacing, spacing, spacing);
0294     mainLayout->setSpacing(spacing);
0295 
0296     // --------------------------------------------------------
0297 
0298     connect(d->subjectsBox, &QListWidget::itemSelectionChanged,
0299             this, &SubjectWidget::slotSubjectSelectionChanged);
0300 
0301     connect(d->addSubjectButton, &QPushButton::clicked,
0302             this, &SubjectWidget::slotAddSubject);
0303 
0304     connect(d->delSubjectButton, &QPushButton::clicked,
0305             this, &SubjectWidget::slotDelSubject);
0306 
0307     connect(d->repSubjectButton, &QPushButton::clicked,
0308             this, &SubjectWidget::slotRepSubject);
0309 
0310 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
0311 
0312     connect(d->btnGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::idReleased),
0313             this, &SubjectWidget::slotEditOptionChanged);
0314 
0315 #else
0316 
0317     connect(d->btnGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonReleased),
0318             this, &SubjectWidget::slotEditOptionChanged);
0319 
0320 #endif
0321 
0322     connect(d->refCB, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
0323             this, &SubjectWidget::slotRefChanged);
0324 
0325     // --------------------------------------------------------
0326 
0327     connect(m_subjectsCheck, &QCheckBox::toggled,
0328             this, &SubjectWidget::slotSubjectsToggled);
0329 
0330     // --------------------------------------------------------
0331 
0332     connect(m_subjectsCheck, &QCheckBox::toggled,
0333             this, &SubjectWidget::signalModified);
0334 
0335     connect(d->addSubjectButton, &QPushButton::clicked,
0336             this, &SubjectWidget::signalModified);
0337 
0338     connect(d->delSubjectButton, &QPushButton::clicked,
0339             this, &SubjectWidget::signalModified);
0340 
0341     connect(d->repSubjectButton, &QPushButton::clicked,
0342             this, &SubjectWidget::signalModified);
0343 
0344     // --------------------------------------------------------
0345 
0346     // NOTE: use dynamic binding as this virtual method can be re-implemented in derived classes.
0347 
0348     this->slotEditOptionChanged(d->btnGroup->id(d->btnGroup->checkedButton()));
0349 }
0350 
0351 SubjectWidget::~SubjectWidget()
0352 {
0353     delete d;
0354 }
0355 
0356 void SubjectWidget::slotSubjectsToggled(bool b)
0357 {
0358     d->optionsBox->setEnabled(b);
0359     d->subjectsBox->setEnabled(b);
0360     d->addSubjectButton->setEnabled(b);
0361     d->delSubjectButton->setEnabled(b);
0362     d->repSubjectButton->setEnabled(b);
0363     slotEditOptionChanged(d->btnGroup->id(d->btnGroup->checkedButton()));
0364 }
0365 
0366 void SubjectWidget::slotEditOptionChanged(int b)
0367 {
0368     if (b == Private::CUSTOM)
0369     {
0370         d->refCB->setEnabled(false);
0371         m_iprEdit->setEnabled(true);
0372         m_refEdit->setEnabled(true);
0373         m_nameEdit->setEnabled(true);
0374         m_matterEdit->setEnabled(true);
0375         m_detailEdit->setEnabled(true);
0376     }
0377     else
0378     {
0379         d->refCB->setEnabled(true);
0380         m_iprEdit->setEnabled(false);
0381         m_refEdit->setEnabled(false);
0382         m_nameEdit->setEnabled(false);
0383         m_matterEdit->setEnabled(false);
0384         m_detailEdit->setEnabled(false);
0385         slotRefChanged();
0386     }
0387 }
0388 
0389 void SubjectWidget::slotRefChanged()
0390 {
0391     QString key = d->refCB->currentText();
0392     QString name, matter, detail;
0393 
0394     for (Private::SubjectCodesMap::Iterator it = d->subMap.begin() ;
0395          it != d->subMap.end() ; ++it)
0396     {
0397         if (key == it.key())
0398         {
0399             name   = it.value().name;
0400             matter = it.value().matter;
0401             detail = it.value().detail;
0402         }
0403     }
0404 
0405     m_refEdit->setText(key);
0406     m_nameEdit->setText(name);
0407     m_matterEdit->setText(matter);
0408     m_detailEdit->setText(detail);
0409 }
0410 
0411 QString SubjectWidget::buildSubject() const
0412 {
0413     QString subject = m_iprEdit->text();
0414 
0415     subject.append(QLatin1Char(':'));
0416     subject.append(m_refEdit->text());
0417     subject.append(QLatin1Char(':'));
0418     subject.append(m_nameEdit->text());
0419     subject.append(QLatin1Char(':'));
0420     subject.append(m_matterEdit->text());
0421     subject.append(QLatin1Char(':'));
0422     subject.append(m_detailEdit->text());
0423 
0424     if (subject.right(4) == QLatin1String("::::"))
0425     {
0426         subject.clear();
0427     }
0428 
0429     return subject;
0430 }
0431 
0432 void SubjectWidget::slotDelSubject()
0433 {
0434     QListWidgetItem* const item = d->subjectsBox->currentItem();
0435 
0436     if (!item)
0437     {
0438         return;
0439     }
0440 
0441     d->subjectsBox->takeItem(d->subjectsBox->row(item));
0442 
0443     delete item;
0444 }
0445 
0446 void SubjectWidget::slotRepSubject()
0447 {
0448     QString newSubject = buildSubject();
0449 
0450     if (newSubject.isEmpty())
0451     {
0452         return;
0453     }
0454 
0455     if (!d->subjectsBox->selectedItems().isEmpty())
0456     {
0457         d->subjectsBox->selectedItems()[0]->setText(newSubject);
0458         m_iprEdit->setText(m_iprDefault);
0459         m_refEdit->clear();
0460         m_nameEdit->clear();
0461         m_matterEdit->clear();
0462         m_detailEdit->clear();
0463     }
0464 }
0465 
0466 void SubjectWidget::slotSubjectSelectionChanged()
0467 {
0468     if (!d->subjectsBox->selectedItems().isEmpty())
0469     {
0470         QString subject = d->subjectsBox->selectedItems()[0]->text();
0471         m_iprEdit->setText(subject.section(QLatin1Char(':'), 0, 0));
0472         m_refEdit->setText(subject.section(QLatin1Char(':'), 1, 1));
0473         m_nameEdit->setText(subject.section(QLatin1Char(':'), 2, 2));
0474         m_matterEdit->setText(subject.section(QLatin1Char(':'), 3, 3));
0475         m_detailEdit->setText(subject.section(QLatin1Char(':'), 4, 4));
0476         d->delSubjectButton->setEnabled(true);
0477         d->repSubjectButton->setEnabled(true);
0478     }
0479     else
0480     {
0481         d->delSubjectButton->setEnabled(false);
0482         d->repSubjectButton->setEnabled(false);
0483     }
0484 }
0485 
0486 void SubjectWidget::slotAddSubject()
0487 {
0488     QString newSubject = buildSubject();
0489 
0490     if (newSubject.isEmpty())
0491     {
0492         return;
0493     }
0494 
0495     bool found = false;
0496 
0497     for (int i = 0 ; i < d->subjectsBox->count() ; ++i)
0498     {
0499         QListWidgetItem* const item = d->subjectsBox->item(i);
0500 
0501         if (newSubject == item->text())
0502         {
0503             found = true;
0504             break;
0505         }
0506     }
0507 
0508     if (!found)
0509     {
0510         d->subjectsBox->insertItem(d->subjectsBox->count(), newSubject);
0511         m_iprEdit->setText(m_iprDefault);
0512         m_refEdit->clear();
0513         m_nameEdit->clear();
0514         m_matterEdit->clear();
0515         m_detailEdit->clear();
0516     }
0517 }
0518 
0519 bool SubjectWidget::loadSubjectCodesFromXML(const QUrl& url)
0520 {
0521     QFile xmlfile(url.toLocalFile());
0522 
0523     if (!xmlfile.open(QIODevice::ReadOnly))
0524     {
0525         return false;
0526     }
0527 
0528     QDomDocument xmlDoc(QLatin1String("NewsML"));
0529 
0530     if (!xmlDoc.setContent(&xmlfile))
0531     {
0532         xmlfile.close();
0533         return false;
0534     }
0535 
0536     QDomElement xmlDocElem = xmlDoc.documentElement();
0537 
0538     if (xmlDocElem.tagName() != QLatin1String("NewsML"))
0539     {
0540         xmlfile.close();
0541         return false;
0542     }
0543 
0544     for (QDomNode nbE1 = xmlDocElem.firstChild() ;
0545          !nbE1.isNull() ; nbE1 = nbE1.nextSibling())
0546     {
0547         QDomElement newsItemElement = nbE1.toElement();
0548 
0549         if (newsItemElement.isNull())
0550         {
0551             continue;
0552         }
0553 
0554         if (newsItemElement.tagName() != QLatin1String("NewsItem"))
0555         {
0556             continue;
0557         }
0558 
0559         for (QDomNode nbE2 = newsItemElement.firstChild() ;
0560             !nbE2.isNull() ; nbE2 = nbE2.nextSibling())
0561         {
0562             QDomElement topicSetElement = nbE2.toElement();
0563 
0564             if (topicSetElement.isNull())
0565             {
0566                 continue;
0567             }
0568 
0569             if (topicSetElement.tagName() != QLatin1String("TopicSet"))
0570             {
0571                 continue;
0572             }
0573 
0574             for (QDomNode nbE3 = topicSetElement.firstChild();
0575                 !nbE3.isNull(); nbE3 = nbE3.nextSibling())
0576             {
0577                 QDomElement topicElement = nbE3.toElement();
0578 
0579                 if (topicElement.isNull())
0580                 {
0581                     continue;
0582                 }
0583 
0584                 if (topicElement.tagName() != QLatin1String("Topic"))
0585                 {
0586                     continue;
0587                 }
0588 
0589                 QString type, name, matter, detail, ref;
0590 
0591                 for (QDomNode nbE4 = topicElement.firstChild();
0592                     !nbE4.isNull(); nbE4 = nbE4.nextSibling())
0593                 {
0594                     QDomElement topicSubElement = nbE4.toElement();
0595 
0596                     if (topicSubElement.isNull())
0597                     {
0598                         continue;
0599                     }
0600 
0601                     if (topicSubElement.tagName() == QLatin1String("TopicType"))
0602                     {
0603                         type = topicSubElement.attribute(QLatin1String("FormalName"));
0604                     }
0605 
0606                     if (topicSubElement.tagName() == QLatin1String("FormalName"))
0607                     {
0608                         ref = topicSubElement.text();
0609                     }
0610 
0611                     if (topicSubElement.tagName() == QLatin1String("Description") &&
0612                         topicSubElement.attribute(QLatin1String("Variant")) == QLatin1String("Name"))
0613                     {
0614                         if      (type == QLatin1String("Subject"))
0615                         {
0616                             name = topicSubElement.text();
0617                         }
0618                         else if (type == QLatin1String("SubjectMatter"))
0619                         {
0620                             matter = topicSubElement.text();
0621                         }
0622                         else if (type == QLatin1String("SubjectDetail"))
0623                         {
0624                             detail = topicSubElement.text();
0625                         }
0626                     }
0627                 }
0628 
0629                 d->subMap.insert(ref, SubjectData(name, matter, detail));
0630             }
0631         }
0632     }
0633 
0634     xmlfile.close();
0635 
0636     // Set the Subject Name everywhere on the map.
0637 
0638     for (Private::SubjectCodesMap::Iterator it = d->subMap.begin() ;
0639          it != d->subMap.end() ; ++it)
0640     {
0641         QString name, keyPrefix;
0642 
0643         if (it.key().endsWith(QLatin1String("00000")))
0644         {
0645             keyPrefix = it.key().left(3);
0646             name      = it.value().name;
0647 
0648             for (Private::SubjectCodesMap::Iterator it2 = d->subMap.begin() ;
0649                  it2 != d->subMap.end() ; ++it2)
0650             {
0651                 if (it2.key().startsWith(keyPrefix) &&
0652                     !it2.key().endsWith(QLatin1String("00000")))
0653                 {
0654                     it2.value().name = name;
0655                 }
0656             }
0657         }
0658     }
0659 
0660     // Set the Subject Matter Name everywhere on the map.
0661 
0662     for (Private::SubjectCodesMap::Iterator it = d->subMap.begin() ;
0663          it != d->subMap.end() ; ++it)
0664     {
0665         QString matter, keyPrefix;
0666 
0667         if (it.key().endsWith(QLatin1String("000")))
0668         {
0669             keyPrefix = it.key().left(5);
0670             matter    = it.value().matter;
0671 
0672             for (Private::SubjectCodesMap::Iterator it2 = d->subMap.begin() ;
0673                 it2 != d->subMap.end() ; ++it2)
0674             {
0675                 if (it2.key().startsWith(keyPrefix) &&
0676                     !it2.key().endsWith(QLatin1String("000")))
0677                 {
0678                     it2.value().matter = matter;
0679                 }
0680             }
0681         }
0682     }
0683 
0684     return true;
0685 }
0686 
0687 void SubjectWidget::setSubjectsList(const QStringList& list)
0688 {
0689     d->subjectsList = list;
0690 
0691     blockSignals(true);
0692     d->subjectsBox->clear();
0693 
0694     if (m_subjectsCheck->isEnabled())
0695     {
0696         m_subjectsCheck->setChecked(false);
0697     }
0698 
0699     if (!d->subjectsList.isEmpty())
0700     {
0701         d->subjectsBox->insertItems(0, d->subjectsList);
0702 
0703         if (m_subjectsCheck->isEnabled())
0704         {
0705             m_subjectsCheck->setChecked(true);
0706         }
0707     }
0708 
0709     blockSignals(false);
0710 
0711     if (m_subjectsCheck->isEnabled())
0712     {
0713         slotSubjectsToggled(m_subjectsCheck->isChecked());
0714     }
0715 }
0716 
0717 QStringList SubjectWidget::subjectsList() const
0718 {
0719     QStringList newSubjects;
0720 
0721     for (int i = 0 ; i < d->subjectsBox->count() ; ++i)
0722     {
0723         QListWidgetItem* item = d->subjectsBox->item(i);
0724         newSubjects.append(item->text());
0725     }
0726 
0727     return newSubjects;
0728 }
0729 
0730 } // namespace Digikam
0731 
0732 #include "moc_subjectwidget.cpp"