File indexing completed on 2024-04-21 05:50:48

0001 /*
0002     SPDX-FileCopyrightText: 2008, 2012, 2014 Rolf Eike Beer <kde@opensource.sf-tec.de>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #ifndef KGPGCHANGEKEY_H
0007 #define KGPGCHANGEKEY_H
0008 
0009 #include "core/kgpgkey.h"
0010 
0011 #include <gpgme.h>
0012 #include <QObject>
0013 #include <QDateTime>
0014 
0015 class KGpgKeyNode;
0016 class KGpgTransaction;
0017 class QWidget;
0018 
0019 /**
0020  * @short A class for changing several properties of a key at once
0021  *
0022  * This class can enable or disable a key and at the same time change owner
0023  * trust and expiration. It may also run in "detached" mode, i.e. the creator
0024  * may be destroyed and the class will finish it's operation and delete itself
0025  * when done.
0026  *
0027  * The class may be reused, i.e. if one change operation finished another one
0028  * can be started (for the same key). It does not take care of any locking,
0029  * the caller must prevent calls to this object while it works.
0030  *
0031  * None of the functions in this object block so it's safe to be called from
0032  * the main application thread (e.g. it will not freeze the GUI).
0033  *
0034  * @author Rolf Eike Beer <kde@opensource.sf-tec.de>
0035  */
0036 class KGpgChangeKey : public QObject
0037 {
0038     Q_OBJECT
0039 
0040 public:
0041     /**
0042      * Creates a change object for a given key node
0043      *
0044      * @param node pointer to key node to take care of
0045      * @param widget parent widget for password dialogs
0046      *
0047      * KGpgChangeKey stores a copy of the key object of the node
0048      * internally to track changes it made. Once everything is
0049      * finished the caller get notified that this node needs refresh.
0050      *
0051      * The widget parameter will not be used to parent this object as
0052      * it may need to run even after the parent window was closed.
0053      * This widget will be used as parent for the transactions so that
0054      * they can show a passphrase prompt with correct widget inheritance,
0055      * otherwise the modal passphrase dialog may be blocked by the modal
0056      * key info dialog. Do not forget to call setParentWidget() if you
0057      * destroy the parent widget while this still needs to run.
0058      */
0059     KGpgChangeKey(KGpgKeyNode *node, QWidget *widget);
0060     /**
0061      * Destroys the object
0062      */
0063     ~KGpgChangeKey() override;
0064 
0065     /**
0066      * Cache new expiration date
0067      *
0068      * @param date new expiration date or QDateTime() if key should get
0069      * unlimited lifetime
0070      */
0071     void setExpiration(const QDateTime &date);
0072 
0073     /**
0074      * Cache new disable flag
0075      *
0076      * @param disable if the key should become disabled or not
0077      */
0078     void setDisable(const bool disable);
0079 
0080     /**
0081      * Cache new owner trust
0082      *
0083      * @param trust new owner trust level
0084      */
0085     void setOwTrust(const gpgme_validity_t trust);
0086 
0087     /**
0088      * Apply all cached changes to the key
0089      *
0090      * @return true if started successfully or false if already running
0091      * (this should never happen).
0092      *
0093      * It is save to call this function if there were no changes to the
0094      * key. It will detect this case and will exit immediately.
0095      *
0096      * The done() signal is emitted when this function has done all the
0097      * work. It is also emitted if the function was called without work to
0098      * do. This case is not considered an error.
0099      */
0100     bool apply();
0101 
0102     /**
0103      * Checks if the cached values differ from those of the key
0104      *
0105      * @return true if the cached values differ from the stored key
0106      *
0107      * This compares the cached values to those of the stored key. If you
0108      * change one value forth and back this function would return false at
0109      * the end.
0110      */
0111     bool wasChanged();
0112 
0113     /**
0114      * Tell the object to remove itself once all work is done
0115      *
0116      * @param applyChanges if pending changes should be applied or dropped
0117      *
0118      * This function may safely be called whether apply() is running or not.
0119      * If applyChanges is set to yes apply() is called and the object
0120      * deletes itself once all changes are done. If apply() already runs
0121      * it is noticed to destruct afterwards. If applyChanges is set to
0122      * false and apply() is not running or if no work has to be done the
0123      * object is destroyed the next time the event loop runs.
0124      */
0125     void selfdestruct(const bool applyChanges);
0126 
0127     /**
0128      * @brief set a new parent widget for the transactions
0129      */
0130     void setParentWidget(QWidget *widget);
0131 Q_SIGNALS:
0132     /**
0133      * This signal gets emitted every time apply() has done all of it's work.
0134      *
0135      * The result argument will be 0 if everything went fine. If no work
0136      * had to be done that was fine, too. If anything goes wrong it will be
0137      * a logic or of every change that caused trouble which can be
0138      * expiration date (1), owner trust (2), or disable (4).
0139      */
0140     void done(int result);
0141 
0142     /**
0143      * This signal get's emitted if apply finishes in detached mode
0144      *
0145      * When the class is in detached mode (i.e. selfdestruct() was called)
0146      * and the key operation finishes this signal is emitted. If apply()
0147      * finishes and the object is not in detached mode only done() is
0148      * emitted.
0149      *
0150      * The reason for this behaviour is that if the owner is around he can
0151      * take care of noticing it's parent when it's the best time (e.g. on
0152      * dialog close). If the owner is gone we need to inform his parent
0153      * about the change ourself. When the owner is around we usually don't
0154      * want to refresh the key immediately as the user might do another
0155      * change and we want to avoid useless refreshes as they are rather
0156      * expensive.
0157      */
0158     void keyNeedsRefresh(KGpgKeyNode *node);
0159 
0160 private Q_SLOTS:
0161     /**
0162      * @internal
0163      */
0164     void nextStep(int result);
0165 
0166 private:
0167     QDateTime m_expiration;
0168     bool m_disable;
0169     gpgme_validity_t m_owtrust;
0170     KgpgCore::KgpgKey m_key;
0171     KGpgKeyNode *m_node;
0172     KGpgTransaction *m_current; ///< the currently active transaction object
0173     QWidget *m_parentWidget;
0174     int m_step;
0175     int m_failed;
0176     bool m_autodestroy;
0177 };
0178 
0179 #endif // KGPGCHANGEKEY_H