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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2007-10-08
0007  * Description : a widget to edit a tag with multiple string entries.
0008  *
0009  * SPDX-FileCopyrightText: 2007-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 "multistringsedit.h"
0016 
0017 // Qt includes
0018 
0019 #include <QCheckBox>
0020 #include <QPushButton>
0021 #include <QGridLayout>
0022 #include <QApplication>
0023 #include <QListWidget>
0024 #include <QToolTip>
0025 
0026 // KDE includes
0027 
0028 #include <klocalizedstring.h>
0029 
0030 // Local includes
0031 
0032 #include "dtextedit.h"
0033 
0034 using namespace Digikam;
0035 
0036 namespace DigikamGenericMetadataEditPlugin
0037 {
0038 
0039 class Q_DECL_HIDDEN MultiStringsEdit::Private
0040 {
0041 public:
0042 
0043     explicit Private()
0044       : addValueButton(nullptr),
0045         delValueButton(nullptr),
0046         repValueButton(nullptr),
0047         valueCheck    (nullptr),
0048         valueEdit     (nullptr),
0049         valueBox      (nullptr)
0050     {
0051     }
0052 
0053     QStringList      oldValues;
0054 
0055     QPushButton*     addValueButton;
0056     QPushButton*     delValueButton;
0057     QPushButton*     repValueButton;
0058 
0059     QCheckBox*       valueCheck;
0060 
0061     DPlainTextEdit*  valueEdit;
0062 
0063     QListWidget*     valueBox;
0064 };
0065 
0066 MultiStringsEdit::MultiStringsEdit(QWidget* const parent,
0067                                    const QString& title,
0068                                    const QString& desc,
0069                                    int size)
0070     : QWidget(parent),
0071       d      (new Private)
0072 {
0073     QGridLayout* const grid = new QGridLayout(this);
0074 
0075     // --------------------------------------------------------
0076 
0077     d->valueCheck     = new QCheckBox(title, this);
0078 
0079     d->addValueButton = new QPushButton(this);
0080     d->delValueButton = new QPushButton(this);
0081     d->repValueButton = new QPushButton(this);
0082     d->addValueButton->setIcon(QIcon::fromTheme(QLatin1String("list-add")));
0083     d->delValueButton->setIcon(QIcon::fromTheme(QLatin1String("edit-delete")));
0084     d->repValueButton->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
0085     d->addValueButton->setWhatsThis(i18n("Add a new value to the list"));
0086     d->delValueButton->setWhatsThis(i18n("Remove the current selected value from the list"));
0087     d->repValueButton->setWhatsThis(i18n("Replace the current selected value from the list"));
0088     d->delValueButton->setEnabled(false);
0089     d->repValueButton->setEnabled(false);
0090 
0091     d->valueBox       = new QListWidget(this);
0092     d->valueBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
0093     d->valueBox->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0094 
0095     d->valueEdit      = new DPlainTextEdit(this);
0096     d->valueEdit->setLinesVisible(1);
0097     QString whatsThis = desc;
0098 
0099     if (size != -1)
0100     {
0101         whatsThis.append(i18n(" This field is limited to:"));
0102         d->valueEdit->setMaxLength(size);
0103         whatsThis.append(i18np("<p>1 character.</p>","<p>%1 characters.</p>", size));
0104 
0105         connect(d->valueEdit, SIGNAL(textChanged()),
0106                 this, SLOT(slotLineEditModified()));
0107     }
0108 
0109     d->valueEdit->setPlaceholderText(desc);
0110     d->valueEdit->setWhatsThis(whatsThis);
0111 
0112     // --------------------------------------------------------
0113 
0114     grid->setAlignment(Qt::AlignTop);
0115     grid->addWidget(d->valueCheck,     0, 0, 1, 1);
0116     grid->addWidget(d->addValueButton, 0, 1, 1, 1);
0117     grid->addWidget(d->delValueButton, 0, 2, 1, 1);
0118     grid->addWidget(d->repValueButton, 0, 3, 1, 1);
0119     grid->addWidget(d->valueBox,       0, 4, 3, 1);
0120     grid->addWidget(d->valueEdit,      2, 0, 1, 4);
0121     grid->setRowStretch(1, 10);
0122     grid->setColumnStretch(0, 10);
0123     grid->setColumnStretch(4, 10);
0124     grid->setContentsMargins(QMargins());
0125     grid->setSpacing(qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0126                           QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)));
0127 
0128     // --------------------------------------------------------
0129 
0130     connect(d->valueBox, SIGNAL(itemSelectionChanged()),
0131             this, SLOT(slotSelectionChanged()));
0132 
0133     connect(d->addValueButton, SIGNAL(clicked()),
0134             this, SLOT(slotAddValue()));
0135 
0136     connect(d->delValueButton, SIGNAL(clicked()),
0137             this, SLOT(slotDeleteValue()));
0138 
0139     connect(d->repValueButton, SIGNAL(clicked()),
0140             this, SLOT(slotReplaceValue()));
0141 
0142     // --------------------------------------------------------
0143 
0144     connect(d->valueCheck, SIGNAL(toggled(bool)),
0145             d->valueEdit, SLOT(setEnabled(bool)));
0146 
0147     connect(d->valueCheck, SIGNAL(toggled(bool)),
0148             d->addValueButton, SLOT(setEnabled(bool)));
0149 
0150     connect(d->valueCheck, SIGNAL(toggled(bool)),
0151             d->delValueButton, SLOT(setEnabled(bool)));
0152 
0153     connect(d->valueCheck, SIGNAL(toggled(bool)),
0154             d->repValueButton, SLOT(setEnabled(bool)));
0155 
0156     connect(d->valueCheck, SIGNAL(toggled(bool)),
0157             d->valueBox, SLOT(setEnabled(bool)));
0158 
0159     // --------------------------------------------------------
0160 
0161     connect(d->valueCheck, SIGNAL(toggled(bool)),
0162             this, SIGNAL(signalModified()));
0163 
0164     connect(d->addValueButton, SIGNAL(clicked()),
0165             this, SIGNAL(signalModified()));
0166 
0167     connect(d->delValueButton, SIGNAL(clicked()),
0168             this, SIGNAL(signalModified()));
0169 
0170     connect(d->repValueButton, SIGNAL(clicked()),
0171             this, SIGNAL(signalModified()));
0172 }
0173 
0174 MultiStringsEdit::~MultiStringsEdit()
0175 {
0176     delete d;
0177 }
0178 
0179 void MultiStringsEdit::slotDeleteValue()
0180 {
0181     QListWidgetItem* const item = d->valueBox->currentItem();
0182 
0183     if (!item)
0184     {
0185         return;
0186     }
0187 
0188     d->valueBox->takeItem(d->valueBox->row(item));
0189     delete item;
0190 }
0191 
0192 void MultiStringsEdit::slotReplaceValue()
0193 {
0194     QString newValue = d->valueEdit->text();
0195 
0196     if (newValue.isEmpty())
0197     {
0198         return;
0199     }
0200 
0201     if (!d->valueBox->selectedItems().isEmpty())
0202     {
0203         d->valueBox->selectedItems()[0]->setText(newValue);
0204         d->valueEdit->clear();
0205     }
0206 }
0207 
0208 void MultiStringsEdit::slotSelectionChanged()
0209 {
0210     if (!d->valueBox->selectedItems().isEmpty())
0211     {
0212         d->valueEdit->setText(d->valueBox->selectedItems()[0]->text());
0213         d->delValueButton->setEnabled(true);
0214         d->repValueButton->setEnabled(true);
0215     }
0216     else
0217     {
0218         d->delValueButton->setEnabled(false);
0219         d->repValueButton->setEnabled(false);
0220     }
0221 }
0222 
0223 void MultiStringsEdit::slotAddValue()
0224 {
0225     QString newValue = d->valueEdit->text();
0226 
0227     if (newValue.isEmpty())
0228     {
0229         return;
0230     }
0231 
0232     bool found = false;
0233 
0234     for (int i = 0 ; i < d->valueBox->count() ; ++i)
0235     {
0236         QListWidgetItem* const item = d->valueBox->item(i);
0237 
0238         if (newValue == item->text())
0239         {
0240             found = true;
0241             break;
0242         }
0243     }
0244 
0245     if (!found)
0246     {
0247         d->valueBox->insertItem(d->valueBox->count(), newValue);
0248         d->valueEdit->clear();
0249     }
0250 }
0251 
0252 void MultiStringsEdit::setValues(const QStringList& values)
0253 {
0254     blockSignals(true);
0255     d->oldValues = values;
0256 
0257     d->valueBox->clear();
0258     d->valueCheck->setChecked(false);
0259 
0260     if (!d->oldValues.isEmpty())
0261     {
0262         d->valueBox->insertItems(0, d->oldValues);
0263         d->valueCheck->setChecked(true);
0264     }
0265 
0266     d->valueEdit->setEnabled(d->valueCheck->isChecked());
0267     d->valueBox->setEnabled(d->valueCheck->isChecked());
0268     d->addValueButton->setEnabled(d->valueCheck->isChecked());
0269     d->delValueButton->setEnabled(d->valueCheck->isChecked());
0270 
0271     blockSignals(false);
0272 }
0273 
0274 bool MultiStringsEdit::getValues(QStringList& oldValues, QStringList& newValues)
0275 {
0276     oldValues = d->oldValues;
0277     newValues.clear();
0278 
0279     for (int i = 0 ; i < d->valueBox->count() ; ++i)
0280     {
0281         QListWidgetItem* const item = d->valueBox->item(i);
0282         newValues.append(item->text());
0283     }
0284 
0285     return d->valueCheck->isChecked();
0286 }
0287 
0288 void MultiStringsEdit::slotLineEditModified()
0289 {
0290     QToolTip::showText(d->valueEdit->mapToGlobal(QPoint(0, (-1)*(d->valueEdit->height() + 16))),
0291                        i18np("%1 character left", "%1 characters left",
0292                        d->valueEdit->maxLength() - d->valueEdit->text().size()),
0293                        d->valueEdit);
0294 }
0295 
0296 } // namespace DigikamGenericMetadataEditPlugin
0297 
0298 #include "moc_multistringsedit.cpp"