File indexing completed on 2024-06-23 05:14:09

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     newcertificatewizard/listwidget.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "listwidget.h"
0013 
0014 #include "ui_listwidget.h"
0015 
0016 #include <QIcon>
0017 
0018 #include <QItemDelegate>
0019 #include <QLineEdit>
0020 #include <QRegularExpressionValidator>
0021 #include <QStringListModel>
0022 
0023 using namespace Kleo::NewCertificateUi;
0024 
0025 namespace
0026 {
0027 
0028 class ItemDelegate : public QItemDelegate
0029 {
0030     Q_OBJECT
0031 public:
0032     explicit ItemDelegate(QObject *p = nullptr)
0033         : QItemDelegate(p)
0034         , m_rx()
0035     {
0036     }
0037     explicit ItemDelegate(const QRegularExpression &rx, QObject *p = nullptr)
0038         : QItemDelegate(p)
0039         , m_rx(rx)
0040     {
0041     }
0042 
0043     void setRegExpFilter(const QRegularExpression &rx)
0044     {
0045         m_rx = rx;
0046     }
0047     const QRegularExpression &regExpFilter() const
0048     {
0049         return m_rx;
0050     }
0051 
0052     QWidget *createEditor(QWidget *p, const QStyleOptionViewItem &o, const QModelIndex &i) const override
0053     {
0054         QWidget *w = QItemDelegate::createEditor(p, o, i);
0055         if (m_rx.isValid())
0056             if (auto const le = qobject_cast<QLineEdit *>(w)) {
0057                 le->setValidator(new QRegularExpressionValidator(m_rx, le));
0058             }
0059         return w;
0060     }
0061 
0062 private:
0063     QRegularExpression m_rx;
0064 };
0065 }
0066 
0067 class ListWidget::Private
0068 {
0069     friend class ::Kleo::NewCertificateUi::ListWidget;
0070     ListWidget *const q;
0071 
0072 public:
0073     explicit Private(ListWidget *qq)
0074         : q(qq)
0075         , stringListModel()
0076         , ui(q)
0077     {
0078         ui.listView->setModel(&stringListModel);
0079         ui.listView->setItemDelegate(&delegate);
0080         connect(ui.listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), q, SLOT(slotSelectionChanged()));
0081         connect(&stringListModel, &QAbstractItemModel::dataChanged, q, &ListWidget::itemsChanged);
0082         connect(&stringListModel, &QAbstractItemModel::rowsInserted, q, &ListWidget::itemsChanged);
0083         connect(&stringListModel, &QAbstractItemModel::rowsRemoved, q, &ListWidget::itemsChanged);
0084     }
0085 
0086 private:
0087     void slotAdd()
0088     {
0089         const int idx = stringListModel.rowCount();
0090         if (stringListModel.insertRows(idx, 1)) {
0091             stringListModel.setData(stringListModel.index(idx), defaultValue);
0092             editRow(idx);
0093         }
0094     }
0095 
0096     void slotRemove()
0097     {
0098         const int idx = selectedRow();
0099         stringListModel.removeRows(idx, 1);
0100         selectRow(idx);
0101     }
0102 
0103     void slotUp()
0104     {
0105         const int idx = selectedRow();
0106         swapRows(idx - 1, idx);
0107         selectRow(idx - 1);
0108     }
0109 
0110     void slotDown()
0111     {
0112         const int idx = selectedRow();
0113         swapRows(idx, idx + 1);
0114         selectRow(idx + 1);
0115     }
0116 
0117     void slotSelectionChanged()
0118     {
0119         enableDisableActions();
0120     }
0121 
0122 private:
0123     void editRow(int idx)
0124     {
0125         const QModelIndex mi = stringListModel.index(idx);
0126         if (!mi.isValid()) {
0127             return;
0128         }
0129         ui.listView->setCurrentIndex(mi);
0130         ui.listView->edit(mi);
0131     }
0132 
0133     QModelIndexList selectedIndexes() const
0134     {
0135         return ui.listView->selectionModel()->selectedRows();
0136     }
0137     int selectedRow() const
0138     {
0139         const QModelIndexList mil = selectedIndexes();
0140         return mil.empty() ? -1 : mil.front().row();
0141     }
0142     void selectRow(int idx)
0143     {
0144         const QModelIndex mi = stringListModel.index(idx);
0145         if (mi.isValid()) {
0146             ui.listView->setCurrentIndex(mi);
0147         }
0148     }
0149     void swapRows(int r1, int r2)
0150     {
0151         if (r1 < 0 || r2 < 0 || r1 >= stringListModel.rowCount() || r2 >= stringListModel.rowCount()) {
0152             return;
0153         }
0154         const QModelIndex m1 = stringListModel.index(r1);
0155         const QModelIndex m2 = stringListModel.index(r2);
0156         const QVariant data1 = m1.data();
0157         const QVariant data2 = m2.data();
0158         stringListModel.setData(m1, data2);
0159         stringListModel.setData(m2, data1);
0160     }
0161     void enableDisableActions()
0162     {
0163         const QModelIndexList mil = selectedIndexes();
0164         ui.removeTB->setEnabled(!mil.empty());
0165         ui.upTB->setEnabled(mil.size() == 1 && mil.front().row() > 0);
0166         ui.downTB->setEnabled(mil.size() == 1 && mil.back().row() < stringListModel.rowCount() - 1);
0167     }
0168 
0169 private:
0170     QStringListModel stringListModel;
0171     ItemDelegate delegate;
0172     QString defaultValue;
0173     struct UI : Ui_ListWidget {
0174         explicit UI(ListWidget *q)
0175             : Ui_ListWidget()
0176         {
0177             setupUi(q);
0178 
0179             addTB->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
0180             addTB->setAccessibleName(i18nc("@action:button", "Add Entry"));
0181             removeTB->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
0182             removeTB->setAccessibleName(i18nc("@action:button", "Remove Entry"));
0183             upTB->setIcon(QIcon::fromTheme(QStringLiteral("go-up")));
0184             upTB->setAccessibleName(i18nc("@action:button", "Move Up"));
0185             downTB->setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
0186             downTB->setAccessibleName(i18nc("@action:button", "Move Down"));
0187         }
0188     } ui;
0189 };
0190 
0191 ListWidget::ListWidget(QWidget *p)
0192     : QWidget(p)
0193     , d(new Private(this))
0194 {
0195 }
0196 
0197 ListWidget::~ListWidget()
0198 {
0199 }
0200 
0201 QStringList ListWidget::items() const
0202 {
0203     return d->stringListModel.stringList();
0204 }
0205 
0206 void ListWidget::setItems(const QStringList &items)
0207 {
0208     d->stringListModel.setStringList(items);
0209 }
0210 
0211 QRegularExpression ListWidget::regExpFilter() const
0212 {
0213     return d->delegate.regExpFilter();
0214 }
0215 
0216 void ListWidget::setRegExpFilter(const QRegularExpression &rx)
0217 {
0218     d->delegate.setRegExpFilter(rx);
0219 }
0220 
0221 QString ListWidget::defaultValue() const
0222 {
0223     return d->defaultValue;
0224 }
0225 
0226 void ListWidget::setDefaultValue(const QString &df)
0227 {
0228     d->defaultValue = df;
0229 }
0230 
0231 #include "listwidget.moc"
0232 #include "moc_listwidget.cpp"