File indexing completed on 2024-05-12 15:55:36

0001 // SPDX-FileCopyrightText: 2019 The KPhotoAlbum Development Team
0002 // SPDX-FileCopyrightText: 2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0003 // SPDX-FileCopyrightText: 2022 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0004 //
0005 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 
0007 #ifndef KPABASE_UIDELEGATE_H
0008 #define KPABASE_UIDELEGATE_H
0009 
0010 #include <QString>
0011 
0012 namespace DB
0013 {
0014 
0015 /**
0016  * @brief The UserFeedback enum enumerates all possible results of a user interaction.
0017  */
0018 enum class UserFeedback {
0019     Confirm ///< The user accepts the dialog, wanting to continue with the action or to say "yes".
0020     ,
0021     Deny ///< The user cancels the dialog, not wanting to continue with the action or to say "no".
0022     ,
0023     SafeDefaultAction ///< The user did not take a choice (maybe there was no user to interact with in the current context, maybe the user closed the dialog). Most often this should mean the same as Demy, not doing any permanent changes.
0024 };
0025 
0026 /**
0027  * @brief The LogMessage struct combines a log message with its category.
0028  * The main intention is to make the UIDelegate method signatures more readable (by avoiding repeated QString parameters).
0029  */
0030 struct LogMessage {
0031     const QLoggingCategory &category; ///< The logging category that shall be used for logging the message.
0032     const QString &message; ///< The log message. Log messages should usually not be localized.
0033 };
0034 
0035 /**
0036  * @brief The UIDelegate class encapsulates possible user interaction and feedback.
0037  * This class is required because in the DB core there should not be any dependency on UI classes.
0038  * Therefore, the usual routine of calling KMessageBox with some parent widget does not work.
0039  *
0040  * The user of the DB core is expected to subclass the pure virtual functions.
0041  * @see FileReader::setUIDelegate()
0042  * @see FileWriter::setUIDelegate()
0043  */
0044 class UIDelegate
0045 {
0046 public:
0047     /**
0048      * @brief Similar to KMessageBox::warningContinueCancel, this method displays a message and prompts the user to continue or cancel.
0049      *
0050      * Additionally, a non-localized log message is logged within the given log category.
0051      * @param logMsg a non-localized log message
0052      * @param msg a localized message
0053      * @param title a localized title for a possible message window
0054      * @param dialogId an ID to identify the dialog (can be used to give the user a "don't ask again" checkbox)
0055      * @return the user choice in form of a UserFeedback
0056      */
0057     UserFeedback warningContinueCancel(const LogMessage logMsg, const QString &msg, const QString &title, const QString &dialogId = QString());
0058 
0059     /**
0060      * @brief Similar to KMessageBox::questionYesNo, this method displays a message and prompts the user for a yes/no answer.
0061      * @param logMsg a non-localized log message
0062      * @param msg a localized message
0063      * @param title a localized title for a possible message window
0064      * @param dialogId an ID to identify the dialog (can be used to give the user a "don't ask again" checkbox)
0065      * @return the user choice in form of a UserFeedback
0066      */
0067     UserFeedback questionYesNo(const LogMessage logMsg, const QString &msg, const QString &title, const QString &dialogId = QString());
0068 
0069     /**
0070      * @brief Displays an informational message to the user.
0071      *
0072      * Additionally, a non-localized log message is logged within the given log category.
0073      * @param logMsg a non-localized log message
0074      * @param msg a localized message
0075      * @param title a localized title for a possible message window
0076      * @param dialogId an ID to identify the dialog (can be used to give the user a "don't ask again" checkbox)
0077      */
0078     void information(const LogMessage logMsg, const QString &msg, const QString &title, const QString &dialogId = QString());
0079     /**
0080      * @brief Displays an error message to the user.
0081      *
0082      * Additionally, a non-localized log message is logged within the given log category.
0083      * @param logMsg a non-localized log message
0084      * @param msg a localized message
0085      * @param title a localized title for a possible message window
0086      * @param dialogId an ID to identify the dialog (can be used to give the user a "don't ask again" checkbox)
0087      */
0088     void error(const LogMessage logMsg, const QString &msg, const QString &title, const QString &dialogId = QString());
0089 
0090     /**
0091      * @brief isDialogDisabled checks whether the user disabled display of a dialog.
0092      * @param dialogId an ID to identify the dialog (can be used to give the user a "don't ask again" checkbox)
0093      * @return \c true, if the dialog was disabled by the user, \c false otherwise.
0094      */
0095     virtual bool isDialogDisabled(const QString &dialogId) = 0;
0096 
0097 protected:
0098     virtual ~UIDelegate() = default;
0099 
0100     virtual UserFeedback askWarningContinueCancel(const QString &msg, const QString &title, const QString &dialogId) = 0;
0101     virtual UserFeedback askQuestionYesNo(const QString &msg, const QString &title, const QString &dialogId) = 0;
0102     virtual void showInformation(const QString &msg, const QString &title, const QString &dialogId) = 0;
0103     virtual void showError(const QString &msg, const QString &title, const QString &dialogId) = 0;
0104 };
0105 
0106 /**
0107  * @brief The DummyUIDelegate class does nothing except returning UserFeedback::DefaultAction on questions.
0108  */
0109 class DummyUIDelegate : public UIDelegate
0110 {
0111 protected:
0112     UserFeedback askWarningContinueCancel(const QString &, const QString &, const QString &) override { return UserFeedback::SafeDefaultAction; }
0113     UserFeedback askQuestionYesNo(const QString &, const QString &, const QString &) override { return UserFeedback::SafeDefaultAction; }
0114     void showInformation(const QString &, const QString &, const QString &) override { }
0115     void showError(const QString &, const QString &, const QString &) override { }
0116 
0117 public:
0118     bool isDialogDisabled(const QString &) override { return false; }
0119 };
0120 
0121 /**
0122  * @brief The AbstractProgressIndicator class provides a generic progress indicator interface.
0123  * It is mostly designed as a UI-agnostic interface that allows a drop-in replacement for QProgressDialog.
0124  */
0125 class AbstractProgressIndicator
0126 {
0127 public:
0128     virtual int minimum() const = 0;
0129     virtual void setMinimum(int min) = 0;
0130     virtual int maximum() const = 0;
0131     virtual void setMaximum(int max) = 0;
0132     virtual int value() = 0;
0133     virtual void setValue(int value) = 0;
0134 
0135     /**
0136      * @brief wasCanceled signals whether a cancellation of the action was requested.
0137      * @return \c true, if the action shall be aborted, or \c false if it shall continue.
0138      */
0139     virtual bool wasCanceled() const = 0;
0140 
0141 protected:
0142     virtual ~AbstractProgressIndicator() {};
0143 };
0144 
0145 template <class Super>
0146 class ProgressDialog : public DB::AbstractProgressIndicator, public Super
0147 {
0148 public:
0149     int minimum() const override
0150     {
0151         return Super::minimum();
0152     }
0153     void setMinimum(int min) override
0154     {
0155         Super::setMinimum(min);
0156     }
0157     int maximum() const override
0158     {
0159         return Super::maximum();
0160     }
0161     void setMaximum(int max) override
0162     {
0163         Super::setMaximum(max);
0164     }
0165     int value() override
0166     {
0167         return Super::value();
0168     }
0169     void setValue(int value) override
0170     {
0171         Super::setValue(value);
0172     }
0173     bool wasCanceled() const override
0174     {
0175         return Super::wasCanceled();
0176     }
0177 };
0178 
0179 class DummyProgressIndicator : public DB::AbstractProgressIndicator
0180 {
0181 public:
0182     int minimum() const override;
0183     void setMinimum(int min) override;
0184     int maximum() const override;
0185     void setMaximum(int max) override;
0186     int value() override;
0187     void setValue(int value) override;
0188     bool wasCanceled() const override;
0189 
0190     void setCancelRequested(bool cancel);
0191 
0192 private:
0193     int m_min = 0;
0194     int m_max = 100;
0195     int m_value = 0;
0196     bool m_cancelRequested = false;
0197 };
0198 } // namespace DB
0199 
0200 #endif // KPABASE_UIDELEGATE_H