1 /*============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2011-03-14
7 * Description : a DConfigDlgWdg to edit IPTC metadata
8 *
9 * Copyright (C) 2006-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2011 by Victor Dodon <dodon dot victor at gmail dot com>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * ============================================================ */
23
24 #include "iptceditwidget.h"
25
26 // Qt includes
27
28 #include <QMenu>
29 #include <QCloseEvent>
30 #include <QKeyEvent>
31 #include <QUrl>
32 #include <QApplication>
33
34 // KDE includes
35
36 #include <ksharedconfig.h>
37 #include <kconfiggroup.h>
38 #include <klocalizedstring.h>
39
40 // Local includes
41
42 #include "digikam_debug.h"
43 #include "metadataedit.h"
44 #include "iptccategories.h"
45 #include "iptccontent.h"
46 #include "iptccredits.h"
47 #include "iptcenvelope.h"
48 #include "iptckeywords.h"
49 #include "iptcorigin.h"
50 #include "iptcproperties.h"
51 #include "iptcstatus.h"
52 #include "iptcsubjects.h"
53 #include "dmetadata.h"
54
55 namespace DigikamGenericMetadataEditPlugin
56 {
57
58 class Q_DECL_HIDDEN IPTCEditWidget::Private
59 {
60
61 public:
62
Private()63 explicit Private()
64 {
65 modified = false;
66 isReadOnly = false;
67 page_content = nullptr;
68 page_properties = nullptr;
69 page_subjects = nullptr;
70 page_keywords = nullptr;
71 page_categories = nullptr;
72 page_credits = nullptr;
73 page_status = nullptr;
74 page_origin = nullptr;
75 page_envelope = nullptr;
76 contentPage = nullptr;
77 propertiesPage = nullptr;
78 subjectsPage = nullptr;
79 keywordsPage = nullptr;
80 categoriesPage = nullptr;
81 creditsPage = nullptr;
82 statusPage = nullptr;
83 originPage = nullptr;
84 envelopePage = nullptr;
85 dlg = nullptr;
86 }
87
88 bool modified;
89 bool isReadOnly;
90
91 DConfigDlgWdgItem* page_content;
92 DConfigDlgWdgItem* page_properties;
93 DConfigDlgWdgItem* page_subjects;
94 DConfigDlgWdgItem* page_keywords;
95 DConfigDlgWdgItem* page_categories;
96 DConfigDlgWdgItem* page_credits;
97 DConfigDlgWdgItem* page_status;
98 DConfigDlgWdgItem* page_origin;
99 DConfigDlgWdgItem* page_envelope;
100
101 IPTCContent* contentPage;
102 IPTCProperties* propertiesPage;
103 IPTCSubjects* subjectsPage;
104 IPTCKeywords* keywordsPage;
105 IPTCCategories* categoriesPage;
106 IPTCCredits* creditsPage;
107 IPTCStatus* statusPage;
108 IPTCOrigin* originPage;
109 IPTCEnvelope* envelopePage;
110
111 MetadataEditDialog* dlg;
112 };
113
IPTCEditWidget(MetadataEditDialog * const parent)114 IPTCEditWidget::IPTCEditWidget(MetadataEditDialog* const parent)
115 : DConfigDlgWdg(parent),
116 d (new Private)
117 {
118 d->dlg = parent;
119
120 d->contentPage = new IPTCContent(this);
121 d->page_content = addPage(d->contentPage, i18nc("@item: iptc", "Content"));
122 d->page_content->setIcon(QIcon::fromTheme(QLatin1String("draw-text")));
123
124 d->originPage = new IPTCOrigin(this);
125 d->page_origin = addPage(d->originPage, i18nc("@item: iptc", "Origin"));
126 d->page_origin->setIcon(QIcon::fromTheme(QLatin1String("globe")));
127
128 d->creditsPage = new IPTCCredits(this);
129 d->page_credits = addPage(d->creditsPage, i18nc("@item: iptc", "Credits"));
130 d->page_credits->setIcon(QIcon::fromTheme(QLatin1String("address-book-new")));
131
132 d->subjectsPage = new IPTCSubjects(this);
133 d->page_subjects = addPage(d->subjectsPage, i18nc("@item: iptc", "Subjects"));
134 d->page_subjects->setIcon(QIcon::fromTheme(QLatin1String("feed-subscribe")));
135
136 d->keywordsPage = new IPTCKeywords(this);
137 d->page_keywords = addPage(d->keywordsPage, i18nc("@item: iptc", "Keywords"));
138 d->page_keywords->setIcon(QIcon::fromTheme(QLatin1String("bookmark-new")));
139
140 d->categoriesPage = new IPTCCategories(this);
141 d->page_categories = addPage(d->categoriesPage, i18nc("@item: iptc", "Categories"));
142 d->page_categories->setIcon(QIcon::fromTheme(QLatin1String("folder-pictures")));
143
144 d->statusPage = new IPTCStatus(this);
145 d->page_status = addPage(d->statusPage, i18nc("@item: iptc", "Status"));
146 d->page_status->setIcon(QIcon::fromTheme(QLatin1String("view-task")));
147
148 d->propertiesPage = new IPTCProperties(this);
149 d->page_properties = addPage(d->propertiesPage, i18nc("@item: iptc", "Properties"));
150 d->page_properties->setIcon(QIcon::fromTheme(QLatin1String("draw-freehand")));
151
152 d->envelopePage = new IPTCEnvelope(this);
153 d->page_envelope = addPage(d->envelopePage, i18nc("@item: iptc", "Envelope"));
154 d->page_envelope->setIcon(QIcon::fromTheme(QLatin1String("mail-mark-unread")));
155
156 // ---------------------------------------------------------------
157
158 connect(d->contentPage, SIGNAL(signalModified()),
159 this, SLOT(slotModified()));
160
161 connect(d->propertiesPage, SIGNAL(signalModified()),
162 this, SLOT(slotModified()));
163
164 connect(d->subjectsPage, SIGNAL(signalModified()),
165 this, SLOT(slotModified()));
166
167 connect(d->keywordsPage, SIGNAL(signalModified()),
168 this, SLOT(slotModified()));
169
170 connect(d->categoriesPage, SIGNAL(signalModified()),
171 this, SLOT(slotModified()));
172
173 connect(d->creditsPage, SIGNAL(signalModified()),
174 this, SLOT(slotModified()));
175
176 connect(d->statusPage, SIGNAL(signalModified()),
177 this, SLOT(slotModified()));
178
179 connect(d->originPage, SIGNAL(signalModified()),
180 this, SLOT(slotModified()));
181
182 connect(d->envelopePage, SIGNAL(signalModified()),
183 this, SLOT(slotModified()));
184
185 // ------------------------------------------------------------
186
187 readSettings();
188 slotItemChanged();
189 }
190
~IPTCEditWidget()191 IPTCEditWidget::~IPTCEditWidget()
192 {
193 delete d;
194 }
195
readSettings()196 void IPTCEditWidget::readSettings()
197 {
198 KSharedConfig::Ptr config = KSharedConfig::openConfig();
199 KConfigGroup group = config->group(QLatin1String("All Metadata Edit Settings"));
200 showPage(group.readEntry(QLatin1String("All IPTC Edit Page"), 0));
201 d->contentPage->setCheckedSyncJFIFComment(group.readEntry(QLatin1String("All Sync JFIF Comment"), true));
202 d->contentPage->setCheckedSyncEXIFComment(group.readEntry(QLatin1String("All Sync EXIF Comment"), true));
203 d->originPage->setCheckedSyncEXIFDate(group.readEntry(QLatin1String("All Sync EXIF Date"), true));
204 }
205
saveSettings()206 void IPTCEditWidget::saveSettings()
207 {
208 KSharedConfig::Ptr config = KSharedConfig::openConfig();
209 KConfigGroup group = config->group(QLatin1String("All Metadata Edit Settings"));
210 group.writeEntry(QLatin1String("All IPTC Edit Page"), activePageIndex());
211 group.writeEntry(QLatin1String("All Sync JFIF Comment"), d->contentPage->syncJFIFCommentIsChecked());
212 group.writeEntry(QLatin1String("All Sync EXIF Comment"), d->contentPage->syncEXIFCommentIsChecked());
213 group.writeEntry(QLatin1String("All Sync EXIF Date"), d->originPage->syncEXIFDateIsChecked());
214 config->sync();
215 }
216
slotItemChanged()217 void IPTCEditWidget::slotItemChanged()
218 {
219 d->page_content->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Content Information\n"
220 "Use this panel to describe the visual content of the image")));
221 d->page_origin->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Origin Information\n"
222 "Use this panel for formal descriptive information about the image")));
223 d->page_credits->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Credit Information\n"
224 "Use this panel to record copyright information about the image")));
225 d->page_subjects->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Subject Information\n"
226 "Use this panel to record subject information about the image")));
227 d->page_keywords->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Keyword Information\n"
228 "Use this panel to record keywords relevant to the image")));
229 d->page_categories->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Category Information\n"
230 "Use this panel to record categories relevant to the image")));
231 d->page_status->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Status Information\n"
232 "Use this panel to record workflow information")));
233 d->page_properties->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Status Properties\n"
234 "Use this panel to record workflow properties")));
235 d->page_envelope->setHeader(d->dlg->currentItemTitleHeader(i18nc("@info", "Envelope Information\n"
236 "Use this panel to record editorial details")));
237
238 QScopedPointer<DMetadata> meta(new DMetadata);
239 meta->load((*d->dlg->currentItem()).toLocalFile());
240
241 d->contentPage->readMetadata(*meta);
242 d->originPage->readMetadata(*meta);
243 d->creditsPage->readMetadata(*meta);
244 d->subjectsPage->readMetadata(*meta);
245 d->keywordsPage->readMetadata(*meta);
246 d->categoriesPage->readMetadata(*meta);
247 d->statusPage->readMetadata(*meta);
248 d->propertiesPage->readMetadata(*meta);
249 d->envelopePage->readMetadata(*meta);
250
251 d->isReadOnly = !DMetadata::canWriteIptc((*d->dlg->currentItem()).toLocalFile());
252 emit signalSetReadOnly(d->isReadOnly);
253
254 d->page_content->setEnabled(!d->isReadOnly);
255 d->page_origin->setEnabled(!d->isReadOnly);
256 d->page_credits->setEnabled(!d->isReadOnly);
257 d->page_subjects->setEnabled(!d->isReadOnly);
258 d->page_keywords->setEnabled(!d->isReadOnly);
259 d->page_categories->setEnabled(!d->isReadOnly);
260 d->page_status->setEnabled(!d->isReadOnly);
261 d->page_properties->setEnabled(!d->isReadOnly);
262 d->page_envelope->setEnabled(!d->isReadOnly);
263 }
264
apply()265 void IPTCEditWidget::apply()
266 {
267 if (d->modified && !d->isReadOnly)
268 {
269 QScopedPointer<DMetadata> meta(new DMetadata);
270 meta->load((*d->dlg->currentItem()).toLocalFile());
271
272 d->contentPage->applyMetadata(*meta);
273 d->originPage->applyMetadata(*meta);
274 d->creditsPage->applyMetadata(*meta);
275 d->subjectsPage->applyMetadata(*meta);
276 d->keywordsPage->applyMetadata(*meta);
277 d->categoriesPage->applyMetadata(*meta);
278 d->statusPage->applyMetadata(*meta);
279 d->propertiesPage->applyMetadata(*meta);
280 d->envelopePage->applyMetadata(*meta);
281
282 meta->applyChanges();
283
284 d->modified = false;
285 }
286 }
287
slotModified()288 void IPTCEditWidget::slotModified()
289 {
290 if (!d->isReadOnly)
291 {
292 d->modified = true;
293 emit signalModified();
294 }
295 }
296
showPage(int page)297 void IPTCEditWidget::showPage(int page)
298 {
299 switch (page)
300 {
301 case 0:
302 setCurrentPage(d->page_content);
303 break;
304 case 1:
305 setCurrentPage(d->page_origin);
306 break;
307 case 2:
308 setCurrentPage(d->page_credits);
309 break;
310 case 3:
311 setCurrentPage(d->page_subjects);
312 break;
313 case 4:
314 setCurrentPage(d->page_keywords);
315 break;
316 case 5:
317 setCurrentPage(d->page_categories);
318 break;
319 case 6:
320 setCurrentPage(d->page_status);
321 break;
322 case 7:
323 setCurrentPage(d->page_properties);
324 break;
325 case 8:
326 setCurrentPage(d->page_envelope);
327 break;
328 default:
329 setCurrentPage(d->page_content);
330 break;
331 }
332 }
333
activePageIndex() const334 int IPTCEditWidget::activePageIndex() const
335 {
336 DConfigDlgWdgItem* const cur = currentPage();
337
338 if (cur == d->page_content) return 0;
339 if (cur == d->page_origin) return 1;
340 if (cur == d->page_credits) return 2;
341 if (cur == d->page_subjects) return 3;
342 if (cur == d->page_keywords) return 4;
343 if (cur == d->page_categories) return 5;
344 if (cur == d->page_status) return 6;
345 if (cur == d->page_properties) return 7;
346 if (cur == d->page_envelope) return 8;
347
348 return 0;
349 }
350
isModified() const351 bool IPTCEditWidget::isModified() const
352 {
353 return d->modified;
354 }
355
356 } // namespace DigikamGenericMetadataEditPlugin
357