1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2007-10-08
7  * Description : a widget to edit Application2 ObjectAttribute
8  *               Iptc tag.
9  *
10  * Copyright (C) 2007-2021 by Gilles Caulier <caulier dot gilles 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 "objectattributesedit.h"
25 
26 // Qt includes
27 
28 #include <QCheckBox>
29 #include <QPushButton>
30 #include <QValidator>
31 #include <QGridLayout>
32 #include <QComboBox>
33 #include <QApplication>
34 #include <QLineEdit>
35 #include <QListWidget>
36 
37 // KDE includes
38 
39 #include <klocalizedstring.h>
40 
41 // Local includes
42 
43 #include "metadatacheckbox.h"
44 #include "squeezedcombobox.h"
45 
46 using namespace Digikam;
47 
48 namespace DigikamGenericMetadataEditPlugin
49 {
50 
51 class Q_DECL_HIDDEN ObjectAttributesEdit::Private
52 {
53 public:
54 
Private()55     explicit Private()
56       : addValueButton(nullptr),
57         delValueButton(nullptr),
58         repValueButton(nullptr),
59         valueEdit     (nullptr),
60         valueBox      (nullptr),
61         valueCheck    (nullptr),
62         dataList      (nullptr)
63     {
64     }
65 
66     QStringList       oldValues;
67 
68     QPushButton*      addValueButton;
69     QPushButton*      delValueButton;
70     QPushButton*      repValueButton;
71 
72     QLineEdit*        valueEdit;
73 
74     QListWidget*      valueBox;
75 
76     MetadataCheckBox* valueCheck;
77 
78     SqueezedComboBox* dataList;
79 };
80 
ObjectAttributesEdit(QWidget * const parent,int size)81 ObjectAttributesEdit::ObjectAttributesEdit(QWidget* const parent, int size)
82     : QWidget(parent),
83       d      (new Private)
84 {
85     QGridLayout* const grid = new QGridLayout(this);
86 
87     // --------------------------------------------------------
88 
89     d->valueCheck     = new MetadataCheckBox(i18n("Attribute:"), this);
90 
91     d->addValueButton = new QPushButton(this);
92     d->delValueButton = new QPushButton(this);
93     d->repValueButton = new QPushButton(this);
94     d->addValueButton->setIcon(QIcon::fromTheme(QLatin1String("list-add")));
95     d->delValueButton->setIcon(QIcon::fromTheme(QLatin1String("edit-delete")));
96     d->repValueButton->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
97     d->addValueButton->setWhatsThis(i18n("Add a new value to the list"));
98     d->delValueButton->setWhatsThis(i18n("Remove the current selected value from the list"));
99     d->repValueButton->setWhatsThis(i18n("Replace the current selected value from the list"));
100     d->delValueButton->setEnabled(false);
101     d->repValueButton->setEnabled(false);
102 
103     d->valueBox       = new QListWidget(this);
104     d->valueBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
105     d->valueBox->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
106 
107     // --------------------------------------------------------
108 
109     d->dataList       = new SqueezedComboBox(this);
110     d->dataList->model()->sort(0);
111     d->dataList->setWhatsThis(i18n("Select here the editorial attribute of content."));
112     d->dataList->addSqueezedItem(QLatin1String("001 - ") + i18nc("Content type", "Current"));
113     d->dataList->addSqueezedItem(QLatin1String("002 - ") + i18nc("Content type", "Analysis"));
114     d->dataList->addSqueezedItem(QLatin1String("003 - ") + i18nc("Content type", "Archive material"));
115     d->dataList->addSqueezedItem(QLatin1String("004 - ") + i18nc("Content type", "Background"));
116     d->dataList->addSqueezedItem(QLatin1String("005 - ") + i18nc("Content type", "Feature"));
117     d->dataList->addSqueezedItem(QLatin1String("006 - ") + i18nc("Content type", "Forecast"));
118     d->dataList->addSqueezedItem(QLatin1String("007 - ") + i18nc("Content type", "History"));
119     d->dataList->addSqueezedItem(QLatin1String("008 - ") + i18nc("Content type", "Obituary"));
120     d->dataList->addSqueezedItem(QLatin1String("009 - ") + i18nc("Content type", "Opinion"));
121     d->dataList->addSqueezedItem(QLatin1String("010 - ") + i18nc("Content type", "Polls & Surveys"));
122     d->dataList->addSqueezedItem(QLatin1String("011 - ") + i18nc("Content type", "Profile"));
123     d->dataList->addSqueezedItem(QLatin1String("012 - ") + i18nc("Content type", "Results Listings & Table"));
124     d->dataList->addSqueezedItem(QLatin1String("013 - ") + i18nc("Content type", "Side bar & Supporting information"));
125     d->dataList->addSqueezedItem(QLatin1String("014 - ") + i18nc("Content type", "Summary"));
126     d->dataList->addSqueezedItem(QLatin1String("015 - ") + i18nc("Content type", "Transcript & Verbatim"));
127     d->dataList->addSqueezedItem(QLatin1String("016 - ") + i18nc("Content type", "Interview"));
128     d->dataList->addSqueezedItem(QLatin1String("017 - ") + i18nc("Content type", "From the Scene"));
129     d->dataList->addSqueezedItem(QLatin1String("018 - ") + i18nc("Content type", "Retrospective"));
130     d->dataList->addSqueezedItem(QLatin1String("019 - ") + i18nc("Content type", "Statistics"));
131     d->dataList->addSqueezedItem(QLatin1String("020 - ") + i18nc("Content type", "Update"));
132     d->dataList->addSqueezedItem(QLatin1String("021 - ") + i18nc("Content type", "Wrap-up"));
133     d->dataList->addSqueezedItem(QLatin1String("022 - ") + i18nc("Content type", "Press Release"));
134 
135     // --------------------------------------------------------
136 
137     d->valueEdit = new QLineEdit(this);
138     d->valueEdit->setClearButtonEnabled(true);
139     QString whatsThis = i18n("Set here the editorial attribute description of "
140                              "content.");
141 
142     if (size != -1)
143     {
144         whatsThis.append(i18n(" This field is limited to "));
145         d->valueEdit->setMaxLength(size);
146         whatsThis.append(i18np("%1 character.","%1 characters.", size));
147     }
148 
149     d->valueEdit->setWhatsThis(whatsThis);
150 
151     // --------------------------------------------------------
152 
153     grid->setAlignment(Qt::AlignTop);
154     grid->addWidget(d->valueCheck,     0, 0, 1, 1);
155     grid->addWidget(d->addValueButton, 0, 1, 1, 1);
156     grid->addWidget(d->delValueButton, 0, 2, 1, 1);
157     grid->addWidget(d->repValueButton, 0, 3, 1, 1);
158     grid->addWidget(d->valueBox,       0, 4, 4, 1);
159     grid->addWidget(d->dataList,       1, 0, 1, 4);
160     grid->addWidget(d->valueEdit,      2, 0, 1, 4);
161     grid->setRowStretch(3, 10);
162     grid->setColumnStretch(0, 10);
163     grid->setColumnStretch(4, 10);
164     grid->setContentsMargins(QMargins());
165     grid->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
166 
167     // --------------------------------------------------------
168 
169     connect(d->valueBox, SIGNAL(itemSelectionChanged()),
170             this, SLOT(slotSelectionChanged()));
171 
172     connect(d->addValueButton, SIGNAL(clicked()),
173             this, SLOT(slotAddValue()));
174 
175     connect(d->delValueButton, SIGNAL(clicked()),
176             this, SLOT(slotDeleteValue()));
177 
178     connect(d->repValueButton, SIGNAL(clicked()),
179             this, SLOT(slotReplaceValue()));
180 
181     // --------------------------------------------------------
182 
183     connect(d->valueCheck, SIGNAL(toggled(bool)),
184             d->valueEdit, SLOT(setEnabled(bool)));
185 
186     connect(d->valueCheck, SIGNAL(toggled(bool)),
187             d->dataList, SLOT(setEnabled(bool)));
188 
189     connect(d->valueCheck, SIGNAL(toggled(bool)),
190             d->addValueButton, SLOT(setEnabled(bool)));
191 
192     connect(d->valueCheck, SIGNAL(toggled(bool)),
193             d->delValueButton, SLOT(setEnabled(bool)));
194 
195     connect(d->valueCheck, SIGNAL(toggled(bool)),
196             d->repValueButton, SLOT(setEnabled(bool)));
197 
198     connect(d->valueCheck, SIGNAL(toggled(bool)),
199             d->valueBox, SLOT(setEnabled(bool)));
200 
201     // --------------------------------------------------------
202 
203     connect(d->valueCheck, SIGNAL(toggled(bool)),
204             this, SIGNAL(signalModified()));
205 
206     connect(d->addValueButton, SIGNAL(clicked()),
207             this, SIGNAL(signalModified()));
208 
209     connect(d->delValueButton, SIGNAL(clicked()),
210             this, SIGNAL(signalModified()));
211 
212     connect(d->repValueButton, SIGNAL(clicked()),
213             this, SIGNAL(signalModified()));
214 }
215 
~ObjectAttributesEdit()216 ObjectAttributesEdit::~ObjectAttributesEdit()
217 {
218     delete d;
219 }
220 
valueEdit() const221 QLineEdit* ObjectAttributesEdit::valueEdit() const
222 {
223     return d->valueEdit;
224 }
225 
slotDeleteValue()226 void ObjectAttributesEdit::slotDeleteValue()
227 {
228     QListWidgetItem* const item = d->valueBox->currentItem();
229 
230     if (!item)
231     {
232         return;
233     }
234 
235     d->valueBox->takeItem(d->valueBox->row(item));
236     delete item;
237 }
238 
slotReplaceValue()239 void ObjectAttributesEdit::slotReplaceValue()
240 {
241     QString newValue = d->dataList->itemHighlighted().left(3);
242     newValue.append(QString::fromUtf8(":%1").arg(d->valueEdit->text()));
243 
244     if (!d->valueBox->selectedItems().isEmpty())
245     {
246         d->valueBox->selectedItems()[0]->setText(newValue);
247     }
248 }
249 
slotSelectionChanged()250 void ObjectAttributesEdit::slotSelectionChanged()
251 {
252     if (!d->valueBox->selectedItems().isEmpty())
253     {
254         bool ok   = false;
255         int index = d->valueBox->selectedItems()[0]->text().section(QLatin1Char(':'), 0, 0).toInt(&ok);
256 
257         if (ok)
258         {
259             d->dataList->setCurrentIndex(index-1);
260             d->valueEdit->setText(d->valueBox->selectedItems()[0]->text().section(QLatin1Char(':'), -1));
261             d->delValueButton->setEnabled(true);
262             d->repValueButton->setEnabled(true);
263             return;
264         }
265     }
266 
267     d->delValueButton->setEnabled(false);
268     d->repValueButton->setEnabled(false);
269 }
270 
slotAddValue()271 void ObjectAttributesEdit::slotAddValue()
272 {
273     QString newValue = d->dataList->itemHighlighted().left(3);
274     newValue.append(QLatin1Char(':'));
275 
276     if (!d->valueEdit->text().isEmpty())
277     {
278         newValue.append(d->valueEdit->text());
279     }
280     else
281     {
282         newValue.append(d->dataList->itemHighlighted()
283                         .section(QLatin1String(" - "), -1));
284     }
285 
286     bool found = false;
287 
288     for (int i = 0 ; i < d->valueBox->count() ; ++i)
289     {
290         QListWidgetItem* const item = d->valueBox->item(i);
291 
292         if (newValue == item->text())
293         {
294             found = true;
295             break;
296         }
297     }
298 
299     if (!found)
300     {
301         d->valueBox->insertItem(d->valueBox->count(), newValue);
302     }
303 }
304 
setValues(const QStringList & values)305 void ObjectAttributesEdit::setValues(const QStringList& values)
306 {
307     blockSignals(true);
308     d->oldValues = values;
309 
310     d->valueBox->clear();
311     d->valueCheck->setChecked(false);
312 
313     if (!d->oldValues.isEmpty())
314     {
315         d->valueBox->insertItems(0, d->oldValues);
316         d->valueCheck->setChecked(true);
317     }
318 
319     d->dataList->setEnabled(d->valueCheck->isChecked());
320     d->valueBox->setEnabled(d->valueCheck->isChecked());
321     d->addValueButton->setEnabled(d->valueCheck->isChecked());
322     d->delValueButton->setEnabled(d->valueCheck->isChecked());
323 
324     blockSignals(false);
325 }
326 
getValues(QStringList & oldValues,QStringList & newValues)327 bool ObjectAttributesEdit::getValues(QStringList& oldValues, QStringList& newValues)
328 {
329     oldValues = d->oldValues;
330     newValues.clear();
331 
332     for (int i = 0 ; i < d->valueBox->count() ; ++i)
333     {
334         QListWidgetItem* const item = d->valueBox->item(i);
335         newValues.append(item->text());
336     }
337 
338     return d->valueCheck->isChecked();
339 }
340 
setValid(bool v)341 void ObjectAttributesEdit::setValid(bool v)
342 {
343     d->valueCheck->setValid(v);
344 }
345 
isValid() const346 bool ObjectAttributesEdit::isValid() const
347 {
348     return d->valueCheck->isValid();
349 }
350 
351 } // namespace DigikamGenericMetadataEditPlugin
352