File indexing completed on 2024-06-23 04:38:07

0001 // SPDX-FileCopyrightText: 2020 Henri Chain <henri.chain@enioka.com>
0002 // SPDX-FileCopyrightText: 2020 Kevin Ottens <kevin.ottens@enioka.com>
0003 //
0004 // SPDX-License-Identifier: LGPL-2.1-or-later
0005 
0006 #ifndef OPTIONALGADGET_H
0007 #define OPTIONALGADGET_H
0008 
0009 #ifdef STD_OPTIONAL_AVAILABLE
0010 #include <optional>
0011 #endif
0012 
0013 #ifdef __cpp_lib_optional
0014 namespace KCGroups
0015 {
0016 template<typename T>
0017 using optional = std::optional<T>;
0018 }
0019 #else
0020 #include "optional.h"
0021 #endif
0022 
0023 #define OPTIONAL_GADGET(T, name)                                                                                                 \
0024     /**                                                                                                                          \
0025      @brief An optional T.                                                                                                       \
0026      The parameterless constructor creates a name without value. \n                                                              \
0027      Use name(const T &val) to create a name with a value. \n                                                                    \
0028      Can be implicitly converted to T (undefined behavior when no value) and to bool (same has hasValue())                       \
0029      */                                                                                                                          \
0030     class KCGROUPS_EXPORT name : public KCGroups::optional<T>                                                                    \
0031     {                                                                                                                            \
0032         Q_GADGET                                                                                                                 \
0033                                                                                                                                  \
0034         /**                                                                                                                      \
0035          @brief The underlying T value. Returns a default T if hasValue() is false. \n                                           \
0036          Has a reset() method to remove the value, which can be reached in QML via x.value = undefined                           \
0037          @accessors getValue(), setValue(), reset()                                                                              \
0038          */                                                                                                                      \
0039         Q_PROPERTY(T value READ getValue WRITE setValue RESET reset)                                                             \
0040                                                                                                                                  \
0041         /**                                                                                                                      \
0042          @brief Whether there is currently a value defined                                                                       \
0043          @accessors hasValue()                                                                                                   \
0044          */                                                                                                                      \
0045         Q_PROPERTY(bool hasValue READ hasValue)                                                                                  \
0046                                                                                                                                  \
0047     public:                                                                                                                      \
0048         /**                                                                                                                      \
0049          The underlying value type. Equal to T                                                                                   \
0050          */                                                                                                                      \
0051         using value_type = T;                                                                                                    \
0052                                                                                                                                  \
0053         using KCGroups::optional<T>::optional;                                                                                   \
0054                                                                                                                                  \
0055         /**                                                                                                                      \
0056          @brief get value or default                                                                                             \
0057          @return underlying value if hasValue() is true, else default T value                                                    \
0058          */                                                                                                                      \
0059         T getValue()                                                                                                             \
0060         {                                                                                                                        \
0061             return *this ? **this : T();                                                                                         \
0062         }                                                                                                                        \
0063                                                                                                                                  \
0064         /**                                                                                                                      \
0065          @brief set a T value                                                                                                    \
0066          @param val: the value to set                                                                                            \
0067          */                                                                                                                      \
0068         void setValue(const T &val)                                                                                              \
0069         {                                                                                                                        \
0070             *reinterpret_cast<KCGroups::optional<T> *>(this) = val;                                                              \
0071         }                                                                                                                        \
0072                                                                                                                                  \
0073         /**                                                                                                                      \
0074          @brief whether a value is currently set                                                                                 \
0075          @return true if a value is present, false otherwise                                                                     \
0076          */                                                                                                                      \
0077         bool hasValue()                                                                                                          \
0078         {                                                                                                                        \
0079             return static_cast<bool>(*this);                                                                                     \
0080         }                                                                                                                        \
0081     };                                                                                                                           \
0082                                                                                                                                  \
0083     inline bool operator==(const name &lhs, const name &rhs)                                                                     \
0084     {                                                                                                                            \
0085         return static_cast<KCGroups::optional<typename name::value_type>>(lhs) ==                                                \
0086             static_cast<KCGroups::optional<typename name::value_type>>(rhs);                                                     \
0087     }                                                                                                                            \
0088                                                                                                                                  \
0089     inline bool operator!=(const name &lhs, const name &rhs)                                                                     \
0090     {                                                                                                                            \
0091         return static_cast<KCGroups::optional<typename name::value_type>>(lhs) !=                                                \
0092             static_cast<KCGroups::optional<typename name::value_type>>(rhs);                                                     \
0093     }                                                                                                                            \
0094                                                                                                                                  \
0095     template<typename U>                                                                                                         \
0096     bool operator==(const name &lhs, const KCGroups::optional<U> &rhs)                                                           \
0097     {                                                                                                                            \
0098         return static_cast<KCGroups::optional<typename name::value_type>>(lhs) == rhs;                                           \
0099     }                                                                                                                            \
0100                                                                                                                                  \
0101     template<typename U>                                                                                                         \
0102     bool operator!=(const name &lhs, const KCGroups::optional<U> &rhs)                                                           \
0103     {                                                                                                                            \
0104         return static_cast<KCGroups::optional<typename name::value_type>>(lhs) != rhs;                                           \
0105     }                                                                                                                            \
0106                                                                                                                                  \
0107     template<typename T>                                                                                                         \
0108     bool operator==(const KCGroups::optional<T> &lhs, const name &rhs)                                                           \
0109     {                                                                                                                            \
0110         return lhs == static_cast<KCGroups::optional<typename name::value_type>>(rhs);                                           \
0111     }                                                                                                                            \
0112                                                                                                                                  \
0113     template<typename T>                                                                                                         \
0114     bool operator!=(const KCGroups::optional<T> &lhs, const name &rhs)                                                           \
0115     {                                                                                                                            \
0116         return lhs != static_cast<KCGroups::optional<typename name::value_type>>(rhs);                                           \
0117     }                                                                                                                            \
0118                                                                                                                                  \
0119     Q_DECLARE_METATYPE(name)                                                                                                     \
0120     static_assert(true, "")
0121 
0122 #endif // OPTIONALGADGET_H