File indexing completed on 2024-06-23 05:14:03
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 dialogs/deletecertificatesdialog.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include <config-kleopatra.h> 0011 0012 #include "deletecertificatesdialog.h" 0013 0014 #include <utils/accessibility.h> 0015 #include <view/keytreeview.h> 0016 0017 #include <Libkleo/KeyListModel> 0018 #include <Libkleo/Stl_Util> 0019 0020 #include "kleopatra_debug.h" 0021 #include <KConfigGroup> 0022 #include <KLocalizedString> 0023 #include <KMessageBox> 0024 #include <KSharedConfig> 0025 #include <KStandardGuiItem> 0026 0027 #include <QCursor> 0028 #include <QDialogButtonBox> 0029 #include <QLabel> 0030 #include <QPushButton> 0031 #include <QTreeView> 0032 #include <QVBoxLayout> 0033 #include <QWhatsThis> 0034 0035 #include <gpgme++/key.h> 0036 0037 using namespace Kleo; 0038 using namespace Kleo::Dialogs; 0039 using namespace GpgME; 0040 0041 class DeleteCertificatesDialog::Private 0042 { 0043 friend class ::Kleo::Dialogs::DeleteCertificatesDialog; 0044 DeleteCertificatesDialog *const q; 0045 0046 public: 0047 explicit Private(DeleteCertificatesDialog *qq) 0048 : q(qq) 0049 , ui(q) 0050 { 0051 } 0052 0053 void slotWhatsThisRequested() 0054 { 0055 qCDebug(KLEOPATRA_LOG); 0056 if (QWidget *const widget = qobject_cast<QWidget *>(q->sender())) 0057 if (!widget->whatsThis().isEmpty()) { 0058 showToolTip(QCursor::pos(), widget->whatsThis(), widget); 0059 } 0060 } 0061 0062 void readConfig() 0063 { 0064 KConfigGroup dialog(KSharedConfig::openStateConfig(), QStringLiteral("DeleteCertificatesDialog")); 0065 ui.selectedKTV.restoreLayout(dialog); 0066 ui.unselectedKTV.restoreLayout(dialog); 0067 const QSize size = dialog.readEntry("Size", QSize(600, 400)); 0068 if (size.isValid()) { 0069 q->resize(size); 0070 } 0071 } 0072 0073 void writeConfig() 0074 { 0075 KConfigGroup dialog(KSharedConfig::openStateConfig(), QStringLiteral("DeleteCertificatesDialog")); 0076 dialog.writeEntry("Size", q->size()); 0077 dialog.sync(); 0078 } 0079 0080 private: 0081 struct UI { 0082 QLabel selectedLB; 0083 KeyTreeView selectedKTV; 0084 QLabel unselectedLB; 0085 KeyTreeView unselectedKTV; 0086 QDialogButtonBox buttonBox; 0087 QVBoxLayout vlay; 0088 0089 explicit UI(DeleteCertificatesDialog *qq) 0090 : selectedLB(i18n("These are the certificates you have selected for deletion:"), qq) 0091 , selectedKTV(qq) 0092 , unselectedLB(i18n("These certificates will be deleted even though you did <b>not</b> " 0093 "explicitly select them (<a href=\"whatsthis://\">Why?</a>):"), 0094 qq) 0095 , unselectedKTV(qq) 0096 , buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel) 0097 , vlay(qq) 0098 { 0099 KDAB_SET_OBJECT_NAME(selectedLB); 0100 KDAB_SET_OBJECT_NAME(selectedKTV); 0101 KDAB_SET_OBJECT_NAME(unselectedLB); 0102 KDAB_SET_OBJECT_NAME(unselectedKTV); 0103 KDAB_SET_OBJECT_NAME(buttonBox); 0104 KDAB_SET_OBJECT_NAME(vlay); 0105 0106 vlay.addWidget(&selectedLB); 0107 vlay.addWidget(&selectedKTV, 1); 0108 vlay.addWidget(&unselectedLB); 0109 vlay.addWidget(&unselectedKTV, 1); 0110 vlay.addWidget(&buttonBox); 0111 0112 const QString unselectedWhatsThis = xi18nc("@info:whatsthis", 0113 "<title>Why do you want to delete more certificates than I selected?</title>" 0114 "<para>When you delete CA certificates (both root CAs and intermediate CAs), " 0115 "the certificates issued by them will also be deleted.</para>" 0116 "<para>This can be nicely seen in <application>Kleopatra</application>'s " 0117 "hierarchical view mode: In this mode, if you delete a certificate that has " 0118 "children, those children will also be deleted. Think of CA certificates as " 0119 "folders containing other certificates: When you delete the folder, you " 0120 "delete its contents, too.</para>"); 0121 unselectedLB.setContextMenuPolicy(Qt::NoContextMenu); 0122 unselectedLB.setWhatsThis(unselectedWhatsThis); 0123 unselectedKTV.setWhatsThis(unselectedWhatsThis); 0124 0125 buttonBox.button(QDialogButtonBox::Ok)->setText(i18nc("@action:button", "Delete")); 0126 0127 connect(&unselectedLB, SIGNAL(linkActivated(QString)), qq, SLOT(slotWhatsThisRequested())); 0128 0129 selectedKTV.setFlatModel(AbstractKeyListModel::createFlatKeyListModel(&selectedKTV)); 0130 unselectedKTV.setFlatModel(AbstractKeyListModel::createFlatKeyListModel(&unselectedKTV)); 0131 0132 selectedKTV.setHierarchicalView(false); 0133 selectedKTV.view()->setSelectionMode(QAbstractItemView::NoSelection); 0134 unselectedKTV.setHierarchicalView(false); 0135 unselectedKTV.view()->setSelectionMode(QAbstractItemView::NoSelection); 0136 0137 connect(&buttonBox, SIGNAL(accepted()), qq, SLOT(accept())); 0138 connect(&buttonBox, &QDialogButtonBox::rejected, qq, &QDialog::reject); 0139 } 0140 } ui; 0141 }; 0142 0143 DeleteCertificatesDialog::DeleteCertificatesDialog(QWidget *p) 0144 : QDialog(p) 0145 , d(new Private(this)) 0146 { 0147 d->readConfig(); 0148 } 0149 0150 DeleteCertificatesDialog::~DeleteCertificatesDialog() 0151 { 0152 d->writeConfig(); 0153 } 0154 0155 void DeleteCertificatesDialog::setSelectedKeys(const std::vector<Key> &keys) 0156 { 0157 d->ui.selectedKTV.setKeys(keys); 0158 } 0159 0160 void DeleteCertificatesDialog::setUnselectedKeys(const std::vector<Key> &keys) 0161 { 0162 d->ui.unselectedLB.setVisible(!keys.empty()); 0163 d->ui.unselectedKTV.setVisible(!keys.empty()); 0164 d->ui.unselectedKTV.setKeys(keys); 0165 } 0166 0167 std::vector<Key> DeleteCertificatesDialog::keys() const 0168 { 0169 const std::vector<Key> sel = d->ui.selectedKTV.keys(); 0170 const std::vector<Key> uns = d->ui.unselectedKTV.keys(); 0171 std::vector<Key> result; 0172 result.reserve(sel.size() + uns.size()); 0173 result.insert(result.end(), sel.begin(), sel.end()); 0174 result.insert(result.end(), uns.begin(), uns.end()); 0175 return result; 0176 } 0177 0178 void DeleteCertificatesDialog::accept() 0179 { 0180 const std::vector<Key> sel = d->ui.selectedKTV.keys(); 0181 const std::vector<Key> uns = d->ui.unselectedKTV.keys(); 0182 0183 const uint secret = 0184 std::count_if(sel.cbegin(), sel.cend(), std::mem_fn(&Key::hasSecret)) + std::count_if(uns.cbegin(), uns.cend(), std::mem_fn(&Key::hasSecret)); 0185 const uint total = sel.size() + uns.size(); 0186 0187 int ret = KMessageBox::Continue; 0188 if (secret) 0189 ret = KMessageBox::warningContinueCancel(this, 0190 secret == total ? i18np("The certificate to be deleted is your own. " 0191 "It contains private key material, " 0192 "which is needed to decrypt past communication " 0193 "encrypted to the certificate, and should therefore " 0194 "not be deleted.", 0195 0196 "All of the certificates to be deleted " 0197 "are your own. " 0198 "They contain private key material, " 0199 "which is needed to decrypt past communication " 0200 "encrypted to the certificate, and should therefore " 0201 "not be deleted.", 0202 0203 secret) 0204 : i18np("One of the certificates to be deleted " 0205 "is your own. " 0206 "It contains private key material, " 0207 "which is needed to decrypt past communication " 0208 "encrypted to the certificate, and should therefore " 0209 "not be deleted.", 0210 0211 "Some of the certificates to be deleted " 0212 "are your own. " 0213 "They contain private key material, " 0214 "which is needed to decrypt past communication " 0215 "encrypted to the certificate, and should therefore " 0216 "not be deleted.", 0217 0218 secret), 0219 i18nc("@title:window", "Secret Key Deletion"), 0220 KStandardGuiItem::guiItem(KStandardGuiItem::Delete), 0221 KStandardGuiItem::cancel(), 0222 QString(), 0223 KMessageBox::Notify | KMessageBox::Dangerous); 0224 0225 if (ret == KMessageBox::Continue) { 0226 QDialog::accept(); 0227 } else { 0228 QDialog::reject(); 0229 } 0230 } 0231 0232 #include "moc_deletecertificatesdialog.cpp"