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