File indexing completed on 2024-05-12 04:44:34

0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT
0003 
0004 // Own headers
0005 // First the interface, which forces the header to be self-contained.
0006 #include "multispinboxsection.h"
0007 // Second, the private implementation.
0008 #include "multispinboxsection_p.h" // IWYU pragma: associated
0009 
0010 #include "constpropagatinguniquepointer.h"
0011 #include "helpermath.h"
0012 #include <qglobal.h>
0013 
0014 namespace PerceptualColor
0015 {
0016 /** @brief Constructor
0017  *
0018  * The object is initialized with default values. */
0019 MultiSpinBoxSection::MultiSpinBoxSection()
0020     : d_pointer(new MultiSpinBoxSectionPrivate())
0021 {
0022 }
0023 
0024 /** @brief Destructor */
0025 MultiSpinBoxSection::~MultiSpinBoxSection() noexcept
0026 {
0027 }
0028 
0029 /** @brief Copy constructor
0030  *
0031  * @param other the object to be copied */
0032 MultiSpinBoxSection::MultiSpinBoxSection(const MultiSpinBoxSection &other)
0033 {
0034     d_pointer.reset(
0035         // Create a copy of the private implementation object
0036         new MultiSpinBoxSectionPrivate(*other.d_pointer));
0037 }
0038 
0039 /** @brief Copy assignment operator
0040  *
0041  * @returns By convention, always returns <tt>*this</tt>.
0042  *
0043  * @param other the object to be copied */
0044 MultiSpinBoxSection &MultiSpinBoxSection::operator=(const MultiSpinBoxSection &other)
0045 {
0046     if (this != &other) { // protect against invalid self-assignment
0047         d_pointer.reset(
0048             // Create a copy of the private implementation object
0049             new MultiSpinBoxSectionPrivate(*other.d_pointer));
0050     }
0051 
0052     return *this; // By convention, always return *this.
0053 }
0054 
0055 /** @brief Move constructor
0056  *
0057  * @param other the object to move */
0058 MultiSpinBoxSection::MultiSpinBoxSection(MultiSpinBoxSection &&other) noexcept
0059 {
0060     d_pointer.swap(other.d_pointer);
0061 }
0062 
0063 /** @brief Move assignment operator
0064  *
0065  * @returns By convention, always returns <tt>*this</tt>.
0066  *
0067  * @param other the object to move-assign */
0068 MultiSpinBoxSection &MultiSpinBoxSection::operator=(MultiSpinBoxSection &&other) noexcept
0069 {
0070     if (this != &other) { // protect against invalid self-assignment
0071         d_pointer.swap(other.d_pointer);
0072     }
0073 
0074     return *this; // By convention, always return *this.
0075 }
0076 
0077 /** @brief The number of digits after the decimal point.
0078  *
0079  * This value can also be <tt>0</tt> to get integer-like behavior.
0080  *
0081  * @returns The property value.
0082  *
0083  * @sa @ref setDecimals */
0084 int MultiSpinBoxSection::decimals() const
0085 {
0086     return d_pointer->m_decimals;
0087 }
0088 
0089 /** @brief Setter for @ref decimals property.
0090  *
0091  * @param newDecimals The new decimals values. */
0092 void MultiSpinBoxSection::setDecimals(int newDecimals)
0093 {
0094     d_pointer->m_decimals = qBound(0, newDecimals, 323);
0095 }
0096 
0097 /** @brief Holds whether or not @ref MultiSpinBox::sectionValues wrap
0098  * around when they reaches @ref minimum or @ref maximum.
0099  *
0100  * The default is <tt>false</tt>.
0101  *
0102  * If <tt>false</tt>, @ref MultiSpinBox::sectionValues shall be bound
0103  * between @ref minimum and  @ref maximum. If <tt>true</tt>,
0104  * @ref MultiSpinBox::sectionValues shall be treated as a circular.
0105  *
0106  * Example: You have a section that displays a value measured in
0107  * degree. @ref minimum is <tt>0</tt>. @ref maximum is <tt>360</tt>.
0108  * The following corrections would be applied to input:
0109  * | Input | isWrapping == false | isWrapping == true |
0110  * | ----: | ------------------: | -----------------: |
0111  * |    -5 |                   0 |                355 |
0112  * |     0 |                   0 |                  0 |
0113  * |     5 |                   5 |                  5 |
0114  * |   355 |                 355 |                355 |
0115  * |   360 |                 360 |                  0 |
0116  * |   365 |                 360 |                  5 |
0117  * |   715 |                 360 |                355 |
0118  * |   720 |                 360 |                  0 |
0119  * |   725 |                 360 |                  5 |
0120  *
0121  * @returns The property value.
0122  *
0123  * @sa @ref setWrapping */
0124 bool MultiSpinBoxSection::isWrapping() const
0125 {
0126     return d_pointer->m_isWrapping;
0127 }
0128 
0129 /** @brief Setter for @ref isWrapping property.
0130  *
0131  * @param newIsWrapping The new isWrapping value. */
0132 void MultiSpinBoxSection::setWrapping(bool newIsWrapping)
0133 {
0134     d_pointer->m_isWrapping = newIsWrapping;
0135 }
0136 
0137 /** @brief The maximum possible value of the section.
0138  *
0139  * @returns The property value.
0140  *
0141  * @sa @ref setMaximum */
0142 double MultiSpinBoxSection::maximum() const
0143 {
0144     return roundToDigits(d_pointer->m_maximum, d_pointer->m_decimals);
0145 }
0146 
0147 /** @brief Setter for @ref maximum property.
0148  *
0149  * @param newMaximum The new maximum value. */
0150 void MultiSpinBoxSection::setMaximum(double newMaximum)
0151 {
0152     d_pointer->m_maximum = newMaximum;
0153     if (d_pointer->m_minimum > d_pointer->m_maximum) {
0154         d_pointer->m_minimum = d_pointer->m_maximum;
0155     }
0156 }
0157 
0158 /** @brief The minimum possible value of the section.
0159  *
0160  * @returns The property value.
0161  *
0162  * @sa @ref setMinimum */
0163 double MultiSpinBoxSection::minimum() const
0164 {
0165     return roundToDigits(d_pointer->m_minimum, d_pointer->m_decimals);
0166 }
0167 
0168 /** @brief Setter for @ref minimum property.
0169  *
0170  * @param newMinimum The new minimum value. */
0171 void MultiSpinBoxSection::setMinimum(double newMinimum)
0172 {
0173     d_pointer->m_minimum = newMinimum;
0174     if (d_pointer->m_maximum < d_pointer->m_minimum) {
0175         d_pointer->m_maximum = d_pointer->m_minimum;
0176     }
0177 }
0178 
0179 /** @brief A prefix to be displayed before the value.
0180  *
0181  * @returns The property value.
0182  *
0183  * @sa @ref setPrefix */
0184 QString MultiSpinBoxSection::prefix() const
0185 {
0186     return d_pointer->m_prefix;
0187 }
0188 
0189 /** @brief Setter for @ref prefix property.
0190  *
0191  * @param newPrefix The new prefix value. */
0192 void MultiSpinBoxSection::setPrefix(const QString &newPrefix)
0193 {
0194     d_pointer->m_prefix = newPrefix;
0195 }
0196 
0197 /** @brief A smaller of two natural steps.
0198  *
0199  * Valid range: >= 0
0200  *
0201  * When the user uses the arrows to change the spin box’s value
0202  * the value will be incremented/decremented by the amount of the
0203  * @ref singleStep.
0204  *
0205  * @returns The property value.
0206  *
0207  * @sa @ref setSingleStep */
0208 double MultiSpinBoxSection::singleStep() const
0209 {
0210     return d_pointer->m_singleStep;
0211 }
0212 
0213 /** @brief Setter for @ref singleStep property.
0214  *
0215  * @param newSingleStep The new single step value. */
0216 void MultiSpinBoxSection::setSingleStep(double newSingleStep)
0217 {
0218     d_pointer->m_singleStep = qMax<double>(0, newSingleStep);
0219 }
0220 
0221 /** @brief The suffix to be displayed behind the value.
0222  *
0223  * @returns The property value.
0224  *
0225  * @sa @ref setSuffix */
0226 QString MultiSpinBoxSection::suffix() const
0227 {
0228     return d_pointer->m_suffix;
0229 }
0230 
0231 /** @brief Setter for @ref suffix property.
0232  *
0233  * @param newSuffix The new suffix value. */
0234 void MultiSpinBoxSection::setSuffix(const QString &newSuffix)
0235 {
0236     d_pointer->m_suffix = newSuffix;
0237 }
0238 
0239 /** @brief Adds QDebug() support for data type
0240  * @ref PerceptualColor::MultiSpinBoxSection
0241  *
0242  * @param dbg Existing debug object
0243  * @param value Value to stream into the debug object
0244  * @returns Debug object with value streamed in */
0245 QDebug operator<<(QDebug dbg, const PerceptualColor::MultiSpinBoxSection &value)
0246 {
0247     dbg.nospace() << "\nMultiSpinBoxSection(" // Opening line
0248                   << "\n    prefix: " << value.prefix() //
0249                   << "\n    minimum: " << value.minimum() //
0250                   << "\n    decimals: " << value.decimals() //
0251                   << "\n    isWrapping: " << value.isWrapping() //
0252                   << "\n    maximum: " << value.maximum() //
0253                   << "\n    suffix: " << value.suffix() //
0254                   << "\n)" // Closing line
0255         ;
0256     return dbg.maybeSpace();
0257 }
0258 
0259 } // namespace PerceptualColor