File indexing completed on 2025-01-05 04:58:21

0001 /*
0002   SPDX-FileCopyrightText: 2015-2024 Laurent Montel <montel@kde.org>
0003 
0004   SPDX-License-Identifier: LGPL-2.0-or-later
0005 
0006 */
0007 
0008 #include "recentaddresswidget.h"
0009 #include "recentaddresses.h"
0010 
0011 #include <KConfig>
0012 #include <KLocalizedString>
0013 #include <KMessageBox>
0014 #include <QLineEdit>
0015 #include <QPushButton>
0016 
0017 #include <QKeyEvent>
0018 #include <QListWidget>
0019 #include <QMenu>
0020 #include <QShortcut>
0021 #include <QToolButton>
0022 #include <QVBoxLayout>
0023 
0024 #include <KEmailValidator>
0025 #include <KLineEditEventHandler>
0026 
0027 using namespace PimCommon;
0028 RecentAddressWidget::RecentAddressWidget(QWidget *parent)
0029     : QWidget(parent)
0030     , mLineEdit(new QLineEdit(this))
0031     , mNewButton(new QToolButton(this))
0032     , mRemoveButton(new QToolButton(this))
0033     , mListView(new QListWidget(this))
0034 {
0035     auto layout = new QVBoxLayout(this);
0036 
0037     auto lineLayout = new QHBoxLayout;
0038     layout->addLayout(lineLayout);
0039 
0040     mLineEdit->setObjectName(QLatin1StringView("line_edit"));
0041     KLineEditEventHandler::catchReturnKey(mLineEdit);
0042     mLineEdit->installEventFilter(this);
0043     mLineEdit->setClearButtonEnabled(true);
0044     mLineEdit->setValidator(new KEmailValidator(this));
0045     mLineEdit->setPlaceholderText(i18n("New email..."));
0046     connect(mLineEdit, &QLineEdit::returnPressed, this, &RecentAddressWidget::slotAddItem);
0047 
0048     lineLayout->addWidget(mLineEdit);
0049 
0050     mNewButton->setToolTip(i18n("Add Email"));
0051     mNewButton->setObjectName(QLatin1StringView("new_button"));
0052     mNewButton->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
0053     mNewButton->setEnabled(false);
0054     connect(mNewButton, &QPushButton::clicked, this, &RecentAddressWidget::slotAddItem);
0055     connect(mLineEdit, &QLineEdit::textChanged, this, &RecentAddressWidget::slotUpdateAddButton);
0056     lineLayout->addWidget(mNewButton);
0057 
0058     mRemoveButton->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
0059     mRemoveButton->setToolTip(i18n("Remove"));
0060     mRemoveButton->setObjectName(QLatin1StringView("remove_button"));
0061     mRemoveButton->setEnabled(false);
0062     lineLayout->addWidget(mRemoveButton);
0063     connect(mRemoveButton, &QPushButton::clicked, this, &RecentAddressWidget::slotRemoveItem);
0064 
0065     auto shortcut = new QShortcut(this);
0066     shortcut->setKey(QKeySequence(Qt::Key_Delete));
0067     connect(shortcut, &QShortcut::activated, this, &RecentAddressWidget::slotRemoveItem);
0068 
0069     mListView->setObjectName(QLatin1StringView("list_view"));
0070     mListView->setSelectionMode(QAbstractItemView::ExtendedSelection);
0071     mListView->setSortingEnabled(true);
0072     mListView->setContextMenuPolicy(Qt::CustomContextMenu);
0073     connect(mListView, &QListWidget::itemSelectionChanged, this, &RecentAddressWidget::updateButtonState);
0074     connect(mListView, &QListWidget::customContextMenuRequested, this, &RecentAddressWidget::slotCustomContextMenuRequested);
0075     layout->addWidget(mListView);
0076     mDirty = false;
0077 }
0078 
0079 RecentAddressWidget::~RecentAddressWidget() = default;
0080 
0081 void RecentAddressWidget::slotUpdateAddButton(const QString &str)
0082 {
0083     mNewButton->setEnabled(!str.trimmed().isEmpty());
0084 }
0085 
0086 void RecentAddressWidget::slotCustomContextMenuRequested(const QPoint &pos)
0087 {
0088     const QList<QListWidgetItem *> selectedItems = mListView->selectedItems();
0089     if (selectedItems.isEmpty()) {
0090         return;
0091     }
0092     QListWidgetItem *item = mListView->itemAt(pos);
0093     if (item) {
0094         QMenu menu(this);
0095         menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")),
0096                        i18np("Remove Email", "Remove Emails", selectedItems.count()),
0097                        this,
0098                        &RecentAddressWidget::slotRemoveItem);
0099         menu.exec(QCursor::pos());
0100     }
0101 }
0102 
0103 void RecentAddressWidget::slotAddItem()
0104 {
0105     const QString newEmail = mLineEdit->text();
0106     if (newEmail.isEmpty()) {
0107         return;
0108     }
0109     const int numberOfItem(mListView->count());
0110     for (int i = 0; i < numberOfItem; ++i) {
0111         if (mListView->item(i)->text() == newEmail) {
0112             return;
0113         }
0114     }
0115 
0116     mListView->insertItem(0, mLineEdit->text());
0117     mListView->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
0118     mLineEdit->clear();
0119     mLineEdit->setFocus();
0120     mDirty = true;
0121     updateButtonState();
0122 }
0123 
0124 void RecentAddressWidget::slotRemoveItem()
0125 {
0126     const QList<QListWidgetItem *> selectedItems = mListView->selectedItems();
0127     if (selectedItems.isEmpty()) {
0128         return;
0129     }
0130     const int answer =
0131         KMessageBox::questionTwoActions(this,
0132                                         i18np("Do you want to remove this email address?", "Do you want to remove %1 email addresses?", selectedItems.count()),
0133                                         i18nc("@title:window", "Remove"),
0134                                         KStandardGuiItem::remove(),
0135                                         KStandardGuiItem::cancel());
0136     if (answer == KMessageBox::ButtonCode::PrimaryAction) {
0137         for (QListWidgetItem *item : selectedItems) {
0138             delete mListView->takeItem(mListView->row(item));
0139         }
0140         mDirty = true;
0141         updateButtonState();
0142     }
0143 }
0144 
0145 void RecentAddressWidget::updateButtonState()
0146 {
0147     QList<QListWidgetItem *> selectedItems = mListView->selectedItems();
0148     const int numberOfElementSelected(selectedItems.count());
0149     mRemoveButton->setEnabled(numberOfElementSelected);
0150     bool enableElement = (numberOfElementSelected <= 1);
0151     mNewButton->setEnabled(enableElement);
0152     mLineEdit->setEnabled(enableElement);
0153 }
0154 
0155 void RecentAddressWidget::setAddresses(const QStringList &addrs)
0156 {
0157     mListView->clear();
0158     mListView->addItems(addrs);
0159 }
0160 
0161 bool RecentAddressWidget::eventFilter(QObject *o, QEvent *e)
0162 {
0163     if (o == mLineEdit && e->type() == QEvent::KeyPress) {
0164         auto keyEvent = static_cast<QKeyEvent *>(e);
0165         if (keyEvent->key() == Qt::Key_Down || keyEvent->key() == Qt::Key_Up) {
0166             return (static_cast<QObject *>(mListView))->event(e);
0167         }
0168     }
0169 
0170     return false;
0171 }
0172 
0173 void RecentAddressWidget::storeAddresses(KConfig *config)
0174 {
0175     const int numberOfItem(mListView->count());
0176     for (int i = 0; i < numberOfItem; ++i) {
0177         PimCommon::RecentAddresses::self(config)->add(mListView->item(i)->text());
0178     }
0179 }
0180 
0181 bool RecentAddressWidget::wasChanged() const
0182 {
0183     return mDirty;
0184 }
0185 
0186 #include "moc_recentaddresswidget.cpp"