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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2011-10-11
0007  * Description : a DConfigDlgWdg to edit XMP metadata
0008  *
0009  * SPDX-FileCopyrightText: 2007-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2011      by Victor Dodon <dodon dot victor at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "xmpeditwidget.h"
0017 
0018 // Qt includes
0019 
0020 #include <QCloseEvent>
0021 #include <QKeyEvent>
0022 #include <QMenu>
0023 #include <QApplication>
0024 #include <QUrl>
0025 #include <QFileInfo>
0026 
0027 // KDE includes
0028 
0029 #include <ksharedconfig.h>
0030 #include <klocalizedstring.h>
0031 #include <kconfiggroup.h>
0032 
0033 // Local includes
0034 
0035 #include "digikam_debug.h"
0036 #include "metadataeditdialog.h"
0037 #include "metaenginesettings.h"
0038 #include "xmpcategories.h"
0039 #include "xmpcontent.h"
0040 #include "xmpcredits.h"
0041 #include "xmpkeywords.h"
0042 #include "xmporigin.h"
0043 #include "xmpproperties.h"
0044 #include "xmpstatus.h"
0045 #include "xmpsubjects.h"
0046 #include "dmetadata.h"
0047 
0048 namespace DigikamGenericMetadataEditPlugin
0049 {
0050 
0051 class Q_DECL_HIDDEN XMPEditWidget::Private
0052 {
0053 
0054 public:
0055 
0056     explicit Private()
0057       : modified       (false),
0058         isReadOnly     (false),
0059         page_content   (nullptr),
0060         page_origin    (nullptr),
0061         page_subjects  (nullptr),
0062         page_keywords  (nullptr),
0063         page_categories(nullptr),
0064         page_credits   (nullptr),
0065         page_status    (nullptr),
0066         page_properties(nullptr),
0067         contentPage    (nullptr),
0068         keywordsPage   (nullptr),
0069         categoriesPage (nullptr),
0070         subjectsPage   (nullptr),
0071         originPage     (nullptr),
0072         creditsPage    (nullptr),
0073         statusPage     (nullptr),
0074         propertiesPage (nullptr),
0075         dlg            (nullptr)
0076     {
0077     }
0078 
0079     bool                  modified;
0080     bool                  isReadOnly;
0081 
0082     DConfigDlgWdgItem*    page_content;
0083     DConfigDlgWdgItem*    page_origin;
0084     DConfigDlgWdgItem*    page_subjects;
0085     DConfigDlgWdgItem*    page_keywords;
0086     DConfigDlgWdgItem*    page_categories;
0087     DConfigDlgWdgItem*    page_credits;
0088     DConfigDlgWdgItem*    page_status;
0089     DConfigDlgWdgItem*    page_properties;
0090 
0091     QList<QUrl>           urls;
0092 
0093     QList<QUrl>::iterator currItem;
0094 
0095     XMPContent*           contentPage;
0096     XMPKeywords*          keywordsPage;
0097     XMPCategories*        categoriesPage;
0098     XMPSubjects*          subjectsPage;
0099     XMPOrigin*            originPage;
0100     XMPCredits*           creditsPage;
0101     XMPStatus*            statusPage;
0102     XMPProperties*        propertiesPage;
0103 
0104     MetadataEditDialog*   dlg;
0105 };
0106 
0107 XMPEditWidget::XMPEditWidget(MetadataEditDialog* const parent)
0108     : DConfigDlgWdg(parent),
0109       d            (new Private)
0110 {
0111     d->dlg           = parent;
0112 
0113     d->contentPage   = new XMPContent(this);
0114     d->page_content  = addPage(d->contentPage, i18nc("@item: xmp content", "Content"));
0115     d->page_content->setIcon(QIcon::fromTheme(QLatin1String("draw-text")));
0116 
0117     d->originPage  = new XMPOrigin(this);
0118     d->page_origin = addPage(d->originPage, i18nc("@item", "Origin"));
0119     d->page_origin->setIcon(QIcon::fromTheme(QLatin1String("globe")));
0120 
0121     d->creditsPage  = new XMPCredits(this);
0122     d->page_credits = addPage(d->creditsPage, i18nc("@item", "Credits"));
0123     d->page_credits->setIcon(QIcon::fromTheme(QLatin1String("address-book-new")));
0124 
0125     d->subjectsPage  = new XMPSubjects(this);
0126     d->page_subjects = addPage(d->subjectsPage, i18nc("@item", "Subjects"));
0127     d->page_subjects->setIcon(QIcon::fromTheme(QLatin1String("feed-subscribe")));
0128 
0129     d->keywordsPage  = new XMPKeywords(this);
0130     d->page_keywords = addPage(d->keywordsPage, i18nc("@item", "Keywords"));
0131     d->page_keywords->setIcon(QIcon::fromTheme(QLatin1String("bookmark-new")));
0132 
0133     d->categoriesPage  = new XMPCategories(this);
0134     d->page_categories = addPage(d->categoriesPage, i18nc("@item", "Categories"));
0135     d->page_categories->setIcon(QIcon::fromTheme(QLatin1String("folder-pictures")));
0136 
0137     d->statusPage  = new XMPStatus(this);
0138     d->page_status = addPage(d->statusPage, i18nc("@item", "Status"));
0139     d->page_status->setIcon(QIcon::fromTheme(QLatin1String("view-task")));
0140 
0141     d->propertiesPage  = new XMPProperties(this);
0142     d->page_properties = addPage(d->propertiesPage, i18nc("@item", "Properties"));
0143     d->page_properties->setIcon(QIcon::fromTheme(QLatin1String("draw-freehand")));
0144 
0145     // ------------------------------------------------------------
0146 
0147     connect(d->contentPage, SIGNAL(signalModified()),
0148             this, SLOT(slotModified()));
0149 
0150     connect(d->propertiesPage, SIGNAL(signalModified()),
0151             this, SLOT(slotModified()));
0152 
0153     connect(d->originPage, SIGNAL(signalModified()),
0154             this, SLOT(slotModified()));
0155 
0156     connect(d->subjectsPage, SIGNAL(signalModified()),
0157             this, SLOT(slotModified()));
0158 
0159     connect(d->keywordsPage, SIGNAL(signalModified()),
0160             this, SLOT(slotModified()));
0161 
0162     connect(d->categoriesPage, SIGNAL(signalModified()),
0163             this, SLOT(slotModified()));
0164 
0165     connect(d->creditsPage, SIGNAL(signalModified()),
0166             this, SLOT(slotModified()));
0167 
0168     connect(d->statusPage, SIGNAL(signalModified()),
0169             this, SLOT(slotModified()));
0170 
0171     // ------------------------------------------------------------
0172 
0173     readSettings();
0174     slotItemChanged();
0175 }
0176 
0177 XMPEditWidget::~XMPEditWidget()
0178 {
0179     delete d;
0180 }
0181 
0182 void XMPEditWidget::readSettings()
0183 {
0184     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0185     KConfigGroup group        = config->group(QLatin1String("All Metadata Edit Settings"));
0186 
0187     showPage(group.readEntry(QLatin1String("All XMP Edit Page"), 0));
0188     d->contentPage->setCheckedSyncJFIFComment(group.readEntry(QLatin1String("All Sync JFIF Comment"),     true));
0189     d->contentPage->setCheckedSyncEXIFComment(group.readEntry(QLatin1String("All Sync EXIF Comment"),     true));
0190     d->contentPage->setCheckedSyncEXIFCopyright(group.readEntry(QLatin1String("All Sync EXIF Copyright"), true));
0191     d->creditsPage->setCheckedSyncEXIFArtist(group.readEntry(QLatin1String("All Sync EXIF Artist"),       true));
0192     d->originPage->setCheckedSyncEXIFDate(group.readEntry(QLatin1String("All Sync EXIF Date"),            true));
0193 }
0194 
0195 void XMPEditWidget::saveSettings()
0196 {
0197     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0198     KConfigGroup group        = config->group(QLatin1String("All Metadata Edit Settings"));
0199 
0200     group.writeEntry(QLatin1String("All XMP Edit Page"),       activePageIndex());
0201     group.writeEntry(QLatin1String("All Sync JFIF Comment"),   d->contentPage->syncJFIFCommentIsChecked());
0202     group.writeEntry(QLatin1String("All Sync EXIF Comment"),   d->contentPage->syncEXIFCommentIsChecked());
0203     group.writeEntry(QLatin1String("All Sync EXIF Copyright"), d->contentPage->syncEXIFCopyrightIsChecked());
0204     group.writeEntry(QLatin1String("All Sync EXIF Artists"),   d->creditsPage->syncEXIFArtistIsChecked());
0205     group.writeEntry(QLatin1String("All Sync EXIF Date"),      d->originPage->syncEXIFDateIsChecked());
0206     config->sync();
0207 }
0208 
0209 void XMPEditWidget::slotItemChanged()
0210 {
0211     d->page_content->setHeader(d->dlg->currentItemTitleHeader(
0212                                    QString::fromUtf8("<qt>%1<br/><i>%2</i></qt>")
0213                                        .arg(i18nc("@title", "Content Information"))
0214                                        .arg(i18nc("@title", "Describe the visual content of the item"))));
0215 
0216     d->page_origin->setHeader(d->dlg->currentItemTitleHeader(
0217                                    QString::fromUtf8("<qt>%1<br/><i>%2</i></qt>")
0218                                        .arg(i18nc("@title", "Origin Information"))
0219                                        .arg(i18nc("@title", "Formal descriptive information about the item"))));
0220 
0221     d->page_credits->setHeader(d->dlg->currentItemTitleHeader(
0222                                    QString::fromUtf8("<qt>%1<br/><i>%2</i></qt>")
0223                                        .arg(i18nc("@title", "Credit Information"))
0224                                        .arg(i18nc("@title", "Record copyright information about the item"))));
0225 
0226     d->page_subjects->setHeader(d->dlg->currentItemTitleHeader(
0227                                    QString::fromUtf8("<qt>%1<br/><i>%2</i></qt>")
0228                                        .arg(i18nc("@title", "Subject Information"))
0229                                        .arg(i18nc("@title", "Record subject information about the item"))));
0230 
0231     d->page_keywords->setHeader(d->dlg->currentItemTitleHeader(
0232                                    QString::fromUtf8("<qt>%1<br/><i>%2</i></qt>")
0233                                        .arg(i18nc("@title", "Keyword Information"))
0234                                        .arg(i18nc("@title", "Record keywords relevant to the item"))));
0235 
0236     d->page_categories->setHeader(d->dlg->currentItemTitleHeader(
0237                                    QString::fromUtf8("<qt>%1<br/><i>%2</i></qt>")
0238                                        .arg(i18nc("@title", "Category Information"))
0239                                        .arg(i18nc("@title", "Record categories relevant to the item"))));
0240 
0241     d->page_status->setHeader(d->dlg->currentItemTitleHeader(
0242                                    QString::fromUtf8("<qt>%1<br/><i>%2</i></qt>")
0243                                        .arg(i18nc("@title", "Status Information"))
0244                                        .arg(i18nc("@title", "Record workflow information"))));
0245 
0246     d->page_properties->setHeader(d->dlg->currentItemTitleHeader(
0247                                    QString::fromUtf8("<qt>%1<br/><i>%2</i></qt>")
0248                                        .arg(i18nc("@title", "Status Properties"))
0249                                        .arg(i18nc("@title", "Record workflow properties"))));
0250 
0251     QScopedPointer<DMetadata> meta(new DMetadata);
0252     meta->load((*d->dlg->currentItem()).toLocalFile());
0253 
0254     d->contentPage->readMetadata(*meta);
0255     d->originPage->readMetadata(*meta);
0256     d->subjectsPage->readMetadata(*meta);
0257     d->keywordsPage->readMetadata(*meta);
0258     d->categoriesPage->readMetadata(*meta);
0259     d->creditsPage->readMetadata(*meta);
0260     d->statusPage->readMetadata(*meta);
0261     d->propertiesPage->readMetadata(*meta);
0262 
0263     d->isReadOnly = (
0264                      (MetaEngineSettings::instance()->settings().metadataWritingMode == DMetadata::WRITE_TO_FILE_ONLY) &&
0265                      !QFileInfo((*d->dlg->currentItem()).toLocalFile()).isWritable()
0266                     );
0267 
0268     Q_EMIT signalSetReadOnly(d->isReadOnly);
0269 
0270     d->page_content->setEnabled(!d->isReadOnly);
0271     d->page_origin->setEnabled(!d->isReadOnly);
0272     d->page_subjects->setEnabled(!d->isReadOnly);
0273     d->page_keywords->setEnabled(!d->isReadOnly);
0274     d->page_categories->setEnabled(!d->isReadOnly);
0275     d->page_credits->setEnabled(!d->isReadOnly);
0276     d->page_status->setEnabled(!d->isReadOnly);
0277     d->page_properties->setEnabled(!d->isReadOnly);
0278 }
0279 
0280 void XMPEditWidget::apply()
0281 {
0282     if (d->modified && !d->isReadOnly)
0283     {
0284         QScopedPointer<DMetadata> meta(new DMetadata);
0285         meta->load((*d->dlg->currentItem()).toLocalFile());
0286 
0287         d->contentPage->applyMetadata(*meta);
0288         d->originPage->applyMetadata(*meta);
0289         d->subjectsPage->applyMetadata(*meta);
0290         d->keywordsPage->applyMetadata(*meta);
0291         d->categoriesPage->applyMetadata(*meta);
0292         d->creditsPage->applyMetadata(*meta);
0293         d->statusPage->applyMetadata(*meta);
0294         d->propertiesPage->applyMetadata(*meta);
0295 
0296         meta->applyChanges();
0297 
0298         d->modified = false;
0299     }
0300 }
0301 
0302 void XMPEditWidget::slotModified()
0303 {
0304     if (!d->isReadOnly)
0305     {
0306         d->modified = true;
0307         Q_EMIT signalModified();
0308     }
0309 }
0310 
0311 void XMPEditWidget::showPage(int page)
0312 {
0313     switch (page)
0314     {
0315         case 0:
0316             setCurrentPage(d->page_content);
0317             break;
0318         case 1:
0319             setCurrentPage(d->page_origin);
0320             break;
0321         case 2:
0322             setCurrentPage(d->page_credits);
0323             break;
0324         case 3:
0325             setCurrentPage(d->page_subjects);
0326             break;
0327         case 4:
0328             setCurrentPage(d->page_keywords);
0329             break;
0330         case 5:
0331             setCurrentPage(d->page_categories);
0332             break;
0333         case 6:
0334             setCurrentPage(d->page_status);
0335             break;
0336         case 7:
0337             setCurrentPage(d->page_properties);
0338             break;
0339         default:
0340             setCurrentPage(d->page_content);
0341             break;
0342     }
0343 }
0344 
0345 int XMPEditWidget::activePageIndex() const
0346 {
0347     DConfigDlgWdgItem* const cur = currentPage();
0348 
0349     if (cur == d->page_content)    return 0;
0350     if (cur == d->page_origin)     return 1;
0351     if (cur == d->page_credits)    return 2;
0352     if (cur == d->page_subjects)   return 3;
0353     if (cur == d->page_keywords)   return 4;
0354     if (cur == d->page_categories) return 5;
0355     if (cur == d->page_status)     return 6;
0356     if (cur == d->page_properties) return 7;
0357 
0358     return 0;
0359 }
0360 
0361 bool XMPEditWidget::isModified() const
0362 {
0363     return d->modified;
0364 }
0365 
0366 } // namespace DigikamGenericMetadataEditPlugin
0367 
0368 #include "moc_xmpeditwidget.cpp"