File indexing completed on 2025-03-09 04:54:30

0001 /*
0002    SPDX-FileCopyrightText: 2019-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "dkimmanageruleswidget.h"
0008 #include "dkimmanagerulescombobox.h"
0009 #include "dkimruledialog.h"
0010 #include "messageviewer_dkimcheckerdebug.h"
0011 #include <KLineEditEventHandler>
0012 #include <KLocalizedString>
0013 #include <KMessageBox>
0014 #include <KTreeWidgetSearchLine>
0015 #include <MessageViewer/DKIMManagerRules>
0016 #include <QHeaderView>
0017 #include <QMenu>
0018 #include <QPointer>
0019 #include <QTreeWidget>
0020 #include <QVBoxLayout>
0021 using namespace MessageViewer;
0022 DKIMManageRulesWidgetItem::DKIMManageRulesWidgetItem(QTreeWidget *parent)
0023     : QTreeWidgetItem(parent)
0024     , mRuleTypeCombobox(new DKIMManageRulesComboBox)
0025 {
0026     treeWidget()->setItemWidget(this, ColumnType::RuleType, mRuleTypeCombobox);
0027 }
0028 
0029 DKIMManageRulesWidgetItem::~DKIMManageRulesWidgetItem() = default;
0030 
0031 MessageViewer::DKIMRule DKIMManageRulesWidgetItem::rule() const
0032 {
0033     MessageViewer::DKIMRule rule;
0034     rule.setEnabled(checkState(ColumnType::Enabled) == Qt::Checked);
0035     rule.setDomain(text(ColumnType::Domain));
0036     rule.setFrom(text(ColumnType::From));
0037     rule.setListId(text(ColumnType::ListId));
0038     rule.setPriority(text(ColumnType::Priority).toInt());
0039     rule.setRuleType(mRuleTypeCombobox->ruleType());
0040     rule.setSignedDomainIdentifier(text(ColumnType::SDid).split(QLatin1Char(' ')));
0041     return rule;
0042 }
0043 
0044 void DKIMManageRulesWidgetItem::setRule(const MessageViewer::DKIMRule &rule)
0045 {
0046     if (mRule != rule) {
0047         mRule = rule;
0048         updateInfo();
0049     }
0050 }
0051 
0052 void DKIMManageRulesWidgetItem::updateInfo()
0053 {
0054     setCheckState(ColumnType::Enabled, mRule.enabled() ? Qt::Checked : Qt::Unchecked);
0055     setText(ColumnType::Domain, mRule.domain());
0056     setText(ColumnType::ListId, mRule.listId());
0057     setText(ColumnType::From, mRule.from());
0058     setText(ColumnType::SDid, mRule.signedDomainIdentifier().join(QLatin1Char(' ')));
0059     setText(ColumnType::Priority, QString::number(mRule.priority()));
0060     mRuleTypeCombobox->setRuleType(mRule.ruleType());
0061 }
0062 
0063 DKIMManageRulesWidget::DKIMManageRulesWidget(QWidget *parent)
0064     : QWidget(parent)
0065     , mTreeWidget(new QTreeWidget(this))
0066 {
0067     auto mainLayout = new QVBoxLayout(this);
0068     mainLayout->setObjectName(QLatin1StringView("mainLayout"));
0069     mainLayout->setContentsMargins({});
0070 
0071     mTreeWidget->setObjectName(QLatin1StringView("treewidget"));
0072     mTreeWidget->setRootIsDecorated(false);
0073     mTreeWidget->setHeaderLabels({i18n("Active"), i18n("Domain"), i18n("List-ID"), i18n("From"), i18n("SDID"), i18n("Rule type"), i18n("Priority")});
0074     mTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
0075     mTreeWidget->setAlternatingRowColors(true);
0076 
0077     auto searchLineEdit = new KTreeWidgetSearchLine(this, mTreeWidget);
0078     searchLineEdit->setObjectName(QLatin1StringView("searchlineedit"));
0079     searchLineEdit->setClearButtonEnabled(true);
0080     mainLayout->addWidget(searchLineEdit);
0081     KLineEditEventHandler::catchReturnKey(searchLineEdit);
0082 
0083     mainLayout->addWidget(mTreeWidget);
0084     connect(mTreeWidget, &QTreeWidget::customContextMenuRequested, this, &DKIMManageRulesWidget::slotCustomContextMenuRequested);
0085     connect(mTreeWidget, &QTreeWidget::itemDoubleClicked, this, [this](QTreeWidgetItem *item) {
0086         if (item) {
0087             auto rulesItem = static_cast<DKIMManageRulesWidgetItem *>(item);
0088             modifyRule(rulesItem);
0089         }
0090     });
0091 }
0092 
0093 DKIMManageRulesWidget::~DKIMManageRulesWidget() = default;
0094 
0095 void DKIMManageRulesWidget::updateRules()
0096 {
0097     const QList<MessageViewer::DKIMRule> rules = MessageViewer::DKIMManagerRules::self()->rules();
0098 
0099     for (const MessageViewer::DKIMRule &rule : rules) {
0100         auto item = new DKIMManageRulesWidgetItem(mTreeWidget);
0101         item->setRule(rule);
0102     }
0103     emitUpdateExportButton();
0104 }
0105 
0106 void DKIMManageRulesWidget::loadSettings()
0107 {
0108     mTreeWidget->setSortingEnabled(true);
0109     mTreeWidget->header()->setSortIndicatorShown(true);
0110     mTreeWidget->header()->setSectionsClickable(true);
0111     mTreeWidget->sortByColumn(0, Qt::AscendingOrder);
0112     updateRules();
0113 }
0114 
0115 QList<MessageViewer::DKIMRule> DKIMManageRulesWidget::rules() const
0116 {
0117     QList<MessageViewer::DKIMRule> rules;
0118     const int total = mTreeWidget->topLevelItemCount();
0119     rules.reserve(total);
0120     for (int i = 0; i < total; ++i) {
0121         QTreeWidgetItem *item = mTreeWidget->topLevelItem(i);
0122         auto ruleItem = static_cast<DKIMManageRulesWidgetItem *>(item);
0123         rules.append(ruleItem->rule());
0124     }
0125     return rules;
0126 }
0127 
0128 void DKIMManageRulesWidget::saveSettings()
0129 {
0130     MessageViewer::DKIMManagerRules::self()->saveRules(rules());
0131 }
0132 
0133 QByteArray DKIMManageRulesWidget::saveHeaders() const
0134 {
0135     return mTreeWidget->header()->saveState();
0136 }
0137 
0138 void DKIMManageRulesWidget::restoreHeaders(const QByteArray &header)
0139 {
0140     mTreeWidget->header()->restoreState(header);
0141 }
0142 
0143 void DKIMManageRulesWidget::addRule()
0144 {
0145     QPointer<DKIMRuleDialog> dlg = new DKIMRuleDialog(this);
0146     if (dlg->exec()) {
0147         const MessageViewer::DKIMRule rule = dlg->rule();
0148         if (rule.isValid()) {
0149             auto item = new DKIMManageRulesWidgetItem(mTreeWidget);
0150             item->setRule(rule);
0151             emitUpdateExportButton();
0152         } else {
0153             qCDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Rule is not valid";
0154         }
0155     }
0156     delete dlg;
0157 }
0158 
0159 void DKIMManageRulesWidget::duplicateRule(DKIMManageRulesWidgetItem *rulesItem)
0160 {
0161     QPointer<DKIMRuleDialog> dlg = new DKIMRuleDialog(this);
0162     dlg->loadRule(rulesItem->rule());
0163     if (dlg->exec()) {
0164         const MessageViewer::DKIMRule rule = dlg->rule();
0165         if (rule.isValid()) {
0166             auto item = new DKIMManageRulesWidgetItem(mTreeWidget);
0167             item->setRule(rule);
0168             emitUpdateExportButton();
0169         }
0170     }
0171     delete dlg;
0172 }
0173 
0174 void DKIMManageRulesWidget::emitUpdateExportButton()
0175 {
0176     Q_EMIT updateExportButton(mTreeWidget->topLevelItemCount() > 0);
0177 }
0178 
0179 void DKIMManageRulesWidget::modifyRule(DKIMManageRulesWidgetItem *rulesItem)
0180 {
0181     QPointer<DKIMRuleDialog> dlg = new DKIMRuleDialog(this);
0182     dlg->loadRule(rulesItem->rule());
0183     if (dlg->exec()) {
0184         const MessageViewer::DKIMRule rule = dlg->rule();
0185         if (rule.isValid()) {
0186             rulesItem->setRule(rule);
0187         }
0188     }
0189     delete dlg;
0190 }
0191 
0192 void DKIMManageRulesWidget::slotCustomContextMenuRequested(const QPoint &pos)
0193 {
0194     QTreeWidgetItem *item = mTreeWidget->itemAt(pos);
0195     QMenu menu(this);
0196     menu.addAction(QIcon::fromTheme(QStringLiteral("list-add")), i18n("Add..."), this, [this]() {
0197         addRule();
0198     });
0199     auto rulesItem = dynamic_cast<DKIMManageRulesWidgetItem *>(item);
0200     if (rulesItem) {
0201         menu.addAction(QIcon::fromTheme(QStringLiteral("document-edit")), i18n("Modify..."), this, [this, rulesItem]() {
0202             modifyRule(rulesItem);
0203         });
0204         menu.addSeparator();
0205         menu.addAction(QIcon::fromTheme(QStringLiteral("edit-duplicate")), i18n("Duplicate Rule"), this, [this, rulesItem]() {
0206             duplicateRule(rulesItem);
0207         });
0208         menu.addSeparator();
0209         menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Remove Rule"), this, [this, item]() {
0210             const int answer = KMessageBox::warningTwoActions(this,
0211                                                               i18n("Do you want to delete this rule?"),
0212                                                               i18nc("@title:window", "Delete Rule"),
0213                                                               KStandardGuiItem::del(),
0214                                                               KStandardGuiItem::cancel());
0215             if (answer == KMessageBox::ButtonCode::PrimaryAction) {
0216                 delete item;
0217                 emitUpdateExportButton();
0218             }
0219         });
0220     }
0221     if (mTreeWidget->topLevelItemCount() > 0) {
0222         menu.addSeparator();
0223         menu.addAction(i18n("Delete All"), this, [this]() {
0224             const int answer = KMessageBox::warningTwoActions(this,
0225                                                               i18n("Do you want to delete all the rules?"),
0226                                                               i18nc("@title:window", "Delete Rules"),
0227                                                               KStandardGuiItem::del(),
0228                                                               KStandardGuiItem::cancel());
0229             if (answer == KMessageBox::ButtonCode::PrimaryAction) {
0230                 mTreeWidget->clear();
0231                 emitUpdateExportButton();
0232             }
0233         });
0234     }
0235     menu.exec(QCursor::pos());
0236 }
0237 
0238 #include "moc_dkimmanageruleswidget.cpp"