File indexing completed on 2024-05-12 05:20:02
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 systemtrayicon.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include <config-kleopatra.h> 0011 0012 #include "systrayicon.h" 0013 0014 #ifndef QT_NO_SYSTEMTRAYICON 0015 0016 #include "kleopatraapplication.h" 0017 #include "mainwindow.h" 0018 0019 #include <smartcard/readerstatus.h> 0020 0021 #include <utils/clipboardmenu.h> 0022 0023 #include <commands/decryptverifyclipboardcommand.h> 0024 #include <commands/encryptclipboardcommand.h> 0025 #include <commands/importcertificatefromclipboardcommand.h> 0026 #include <commands/learncardkeyscommand.h> 0027 #include <commands/setinitialpincommand.h> 0028 #include <commands/signclipboardcommand.h> 0029 0030 #include <KAboutApplicationDialog> 0031 #include <KAboutData> 0032 #include <KActionMenu> 0033 #include <KLocalizedString> 0034 #include <QEventLoopLocker> 0035 #include <QIcon> 0036 0037 #include <QAction> 0038 #include <QApplication> 0039 #include <QMenu> 0040 #include <QPointer> 0041 #include <QSignalBlocker> 0042 0043 using namespace Kleo; 0044 using namespace Kleo::Commands; 0045 using namespace Kleo::SmartCard; 0046 0047 class SysTrayIcon::Private 0048 { 0049 friend class ::SysTrayIcon; 0050 SysTrayIcon *const q; 0051 0052 public: 0053 explicit Private(SysTrayIcon *qq); 0054 ~Private(); 0055 0056 private: 0057 void slotAbout() 0058 { 0059 if (!aboutDialog) { 0060 aboutDialog = new KAboutApplicationDialog(KAboutData::applicationData()); 0061 aboutDialog->setAttribute(Qt::WA_DeleteOnClose); 0062 } 0063 0064 if (aboutDialog->isVisible()) { 0065 aboutDialog->raise(); 0066 } else { 0067 aboutDialog->show(); 0068 } 0069 } 0070 0071 void enableDisableActions() 0072 { 0073 openCertificateManagerAction.setEnabled(!q->mainWindow() || !q->mainWindow()->isVisible()); 0074 setInitialPinAction.setEnabled(!firstCardWithNullPin.empty()); 0075 learnCertificatesAction.setEnabled(anyCardCanLearnKeys); 0076 0077 q->setAttentionWanted((!firstCardWithNullPin.empty() || anyCardCanLearnKeys) && !q->attentionWindow()); 0078 } 0079 0080 void slotSetInitialPin() 0081 { 0082 if (!firstCardWithNullPin.empty()) { 0083 auto cmd = new SetInitialPinCommand(firstCardWithNullPin); 0084 q->setAttentionWindow(cmd->dialog()); 0085 startCommand(cmd); 0086 } 0087 } 0088 0089 void slotLearnCertificates() 0090 { 0091 auto cmd = new LearnCardKeysCommand(GpgME::CMS); 0092 q->setAttentionWindow(cmd->dialog()); 0093 startCommand(cmd); 0094 } 0095 void startCommand(Command *cmd) 0096 { 0097 Q_ASSERT(cmd); 0098 cmd->setParent(q->mainWindow()); 0099 cmd->start(); 0100 } 0101 0102 private: 0103 std::string firstCardWithNullPin; 0104 bool anyCardCanLearnKeys = false; 0105 bool learningInProgress = false; 0106 0107 QMenu menu; 0108 QAction openCertificateManagerAction; 0109 QAction configureAction; 0110 QAction aboutAction; 0111 QAction quitAction; 0112 0113 ClipboardMenu clipboardMenu; 0114 0115 QMenu cardMenu; 0116 QAction updateCardStatusAction; 0117 QAction setInitialPinAction; 0118 QAction learnCertificatesAction; 0119 0120 QPointer<KAboutApplicationDialog> aboutDialog; 0121 QEventLoopLocker eventLoopLocker; 0122 }; 0123 0124 SysTrayIcon::Private::Private(SysTrayIcon *qq) 0125 : q(qq) 0126 , menu() 0127 , openCertificateManagerAction(i18nc("@action:inmenu", "&Open Certificate Manager..."), q) 0128 , configureAction(QIcon::fromTheme(QStringLiteral("configure")), 0129 xi18nc("@action:inmenu", "&Configure <application>%1</application>...", KAboutData::applicationData().displayName()), 0130 q) 0131 , aboutAction(QIcon::fromTheme(QStringLiteral("kleopatra")), 0132 xi18nc("@action:inmenu", "&About <application>%1</application>...", KAboutData::applicationData().displayName()), 0133 q) 0134 , quitAction(QIcon::fromTheme(QStringLiteral("application-exit")), 0135 xi18nc("@action:inmenu", "&Shutdown <application>%1</application>", KAboutData::applicationData().displayName()), 0136 q) 0137 , clipboardMenu(q) 0138 , cardMenu(i18nc("@title:menu", "SmartCard")) 0139 , updateCardStatusAction(i18nc("@action:inmenu", "Update Card Status"), q) 0140 , setInitialPinAction(i18nc("@action:inmenu", "Set NetKey v3 Initial PIN..."), q) 0141 , learnCertificatesAction(i18nc("@action:inmenu", "Learn NetKey v3 Card Certificates"), q) 0142 , aboutDialog() 0143 { 0144 q->setNormalIcon(QIcon::fromTheme(QStringLiteral("kleopatra"))); 0145 q->setAttentionIcon(QIcon::fromTheme(QStringLiteral("auth-sim-locked"))); 0146 0147 KDAB_SET_OBJECT_NAME(menu); 0148 KDAB_SET_OBJECT_NAME(openCertificateManagerAction); 0149 KDAB_SET_OBJECT_NAME(configureAction); 0150 KDAB_SET_OBJECT_NAME(aboutAction); 0151 KDAB_SET_OBJECT_NAME(quitAction); 0152 KDAB_SET_OBJECT_NAME(clipboardMenu); 0153 KDAB_SET_OBJECT_NAME(cardMenu); 0154 KDAB_SET_OBJECT_NAME(setInitialPinAction); 0155 KDAB_SET_OBJECT_NAME(learnCertificatesAction); 0156 0157 connect(&openCertificateManagerAction, SIGNAL(triggered()), qApp, SLOT(openOrRaiseMainWindow())); 0158 connect(&configureAction, SIGNAL(triggered()), qApp, SLOT(openOrRaiseConfigDialog())); 0159 connect(&aboutAction, SIGNAL(triggered()), q, SLOT(slotAbout())); 0160 connect(&quitAction, &QAction::triggered, QCoreApplication::instance(), &QCoreApplication::quit); 0161 connect(&updateCardStatusAction, &QAction::triggered, ReaderStatus::instance(), &ReaderStatus::updateStatus); 0162 connect(&setInitialPinAction, SIGNAL(triggered()), q, SLOT(slotSetInitialPin())); 0163 connect(&learnCertificatesAction, SIGNAL(triggered()), q, SLOT(slotLearnCertificates())); 0164 0165 menu.addAction(&openCertificateManagerAction); 0166 menu.addAction(&configureAction); 0167 menu.addAction(&aboutAction); 0168 menu.addSeparator(); 0169 menu.addMenu(clipboardMenu.clipboardMenu()->menu()); 0170 menu.addSeparator(); 0171 menu.addMenu(&cardMenu); 0172 cardMenu.addAction(&updateCardStatusAction); 0173 cardMenu.addAction(&setInitialPinAction); 0174 cardMenu.addAction(&learnCertificatesAction); 0175 menu.addSeparator(); 0176 menu.addAction(&quitAction); 0177 0178 q->setContextMenu(&menu); 0179 clipboardMenu.setMainWindow(q->mainWindow()); 0180 } 0181 0182 SysTrayIcon::Private::~Private() 0183 { 0184 } 0185 0186 SysTrayIcon::SysTrayIcon(QObject *p) 0187 : SystemTrayIcon(p) 0188 , d(new Private(this)) 0189 { 0190 slotEnableDisableActions(); 0191 } 0192 0193 SysTrayIcon::~SysTrayIcon() 0194 { 0195 } 0196 0197 MainWindow *SysTrayIcon::mainWindow() const 0198 { 0199 return static_cast<MainWindow *>(SystemTrayIcon::mainWindow()); 0200 } 0201 0202 QDialog *SysTrayIcon::attentionWindow() const 0203 { 0204 return static_cast<QDialog *>(SystemTrayIcon::attentionWindow()); 0205 } 0206 0207 void SysTrayIcon::doActivated() 0208 { 0209 if (const QWidget *const aw = attentionWindow()) 0210 if (aw->isVisible()) { 0211 return; // ignore clicks while an attention window is open. 0212 } 0213 if (!d->firstCardWithNullPin.empty()) { 0214 d->slotSetInitialPin(); 0215 } else if (d->anyCardCanLearnKeys) { 0216 d->slotLearnCertificates(); 0217 } else { 0218 // Toggle visibility of MainWindow 0219 KleopatraApplication::instance()->toggleMainWindowVisibility(); 0220 } 0221 } 0222 0223 void SysTrayIcon::setFirstCardWithNullPin(const std::string &serialNumber) 0224 { 0225 if (d->firstCardWithNullPin == serialNumber) { 0226 return; 0227 } 0228 d->firstCardWithNullPin = serialNumber; 0229 slotEnableDisableActions(); 0230 } 0231 0232 void SysTrayIcon::setAnyCardCanLearnKeys(bool on) 0233 { 0234 if (d->anyCardCanLearnKeys == on || d->learningInProgress) { 0235 return; 0236 } 0237 d->anyCardCanLearnKeys = on; 0238 slotEnableDisableActions(); 0239 } 0240 0241 void SysTrayIcon::slotEnableDisableActions() 0242 { 0243 d->enableDisableActions(); 0244 } 0245 0246 /* We need this as the readerstatus might update even 0247 * while the loading is in progress. */ 0248 void SysTrayIcon::setLearningInProgress(bool value) 0249 { 0250 if (value) { 0251 setAnyCardCanLearnKeys(false); 0252 } 0253 d->learningInProgress = value; 0254 } 0255 0256 #include "moc_systrayicon.cpp" 0257 0258 #endif // QT_NO_SYSTEMTRAYICON