File indexing completed on 2024-12-01 10:29:04
0001 /* This file is part of the KDE project 0002 Copyright (C) 2004-2012 Jarosław Staniek <staniek@kde.org> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this program; see the file COPYING. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #ifndef KDB_TRISTATE_H 0021 #define KDB_TRISTATE_H 0022 0023 #include <QString> 0024 #include <QtDebug> 0025 0026 enum tristate_cancelled_t { 0027 /** 0028 * @e cancelled value, in most cases usable if there is a need for returning 0029 * @e cancelled value explicitly. Example use: 0030 * @code 0031 * tristate myFunctionThatCanBeCancelled() { 0032 * doSomething(); 0033 * if (userCancelledOperation()) 0034 * return cancelled; //neither success or failure is returned here 0035 * return operationSucceeded(); //return success or failure 0036 * } 0037 * @endcode 0038 * Even though ~ operator of tristate class can be used, it is also possible to test: 0039 * @code 0040 * if (cancelled == myFunctionThatCanBeCancelled()) { .... } 0041 * @endcode 0042 */ 0043 cancelled, 0044 0045 /** 0046 * Convenience name, the same as cancelled value. 0047 */ 0048 dontKnow = cancelled 0049 }; 0050 0051 /** 0052 * 3-state logical type with three values: @e true, @e false and @e cancelled and convenient operators. 0053 * 0054 * @e cancelled state can be also called @e dontKnow, it behaves as @e null in SQL. 0055 * A main goal of this class is to improve readibility when there's a need 0056 * for storing third, @e cancelled, state, especially in case C++ exceptions are not in use. 0057 * With it, developer can forget about declaring a specific enum type 0058 * having just three values: @e true, @e false, @e cancelled. 0059 * 0060 * Objects of this class can be used with similar convenience as standard bool type: 0061 * - use as return value when 'cancelled' 0062 * @code 0063 * tristate doSomething(); 0064 * @endcode 0065 * - convert from bool (1) or to bool (2) 0066 * @code 0067 * tristate t = true; //(1) 0068 * setVisible(t); //(2) 0069 * @endcode 0070 * - clear comparisons 0071 * @code 0072 * tristate t = doSomething(); 0073 * if (t) doSomethingIfTrue(); 0074 * if (!t) doSomethingIfFalse(); 0075 * if (~t) doSomethingIfCancelled(); 0076 * @endcode 0077 * 0078 * "! ~" can be used as "not cancelled". 0079 * 0080 * With tristate class, developer can also forget about 0081 * it's additional meaning and treat it just as a bool, if the third state 0082 * is irrelevant to the current situation. 0083 * 0084 * Other use for tristate class could be to allow cancellation within 0085 * a callback function or a Qt slot. Example: 0086 * @code 0087 * public Q_SLOTS: 0088 * void validateData(tristate *result); 0089 * @endcode 0090 * Having the single parameter, signals and slots have still simple look. 0091 * Developers can alter their code (by replacing 'bool *result' with 'tristate *result') 0092 * in case when a possibility of canceling of, say, data provessing needs to be implemented. 0093 * Let's say @e validateData() function uses a QDialog to get some validation from a user. 0094 * While QDialog::Rejected is returned after cancellation of the validation process, 0095 * the information about cancellation needs to be transferred up to a higher level of the program. 0096 * Storing values of type QDialog::DialogCode there could be found as unreadable, and 0097 * casting these to int is not typesafe. With tristate class it's easier to make it obvious that 0098 * cancellation should be taken into account. 0099 */ 0100 class tristate 0101 { 0102 public: 0103 /** 0104 * Default constructor, object has @e cancelled value set. 0105 */ 0106 inline tristate() 0107 : m_value(Cancelled) { 0108 } 0109 0110 /** 0111 * Constructor accepting a boolean value. 0112 */ 0113 inline tristate(bool boolValue) 0114 : m_value(boolValue ? True : False) { 0115 } 0116 0117 /** 0118 * Constructor accepting a char value. 0119 * It is converted in the following way: 0120 * - 2 -> cancelled 0121 * - 1 -> true 0122 * - other -> false 0123 */ 0124 inline tristate(tristate_cancelled_t) 0125 : m_value(tristate::Cancelled) { 0126 } 0127 0128 /** 0129 * Casting to bool type with negation: true is only returned 0130 * if the original tristate value is equal to false. 0131 */ 0132 inline bool operator!() const { 0133 return m_value == False; 0134 } 0135 0136 /** 0137 * Special casting to bool type: true is only returned 0138 * if the original tristate value is equal to @e cancelled. 0139 */ 0140 inline bool operator~() const { 0141 return m_value == Cancelled; 0142 } 0143 0144 inline tristate& operator=(tristate tsValue); 0145 0146 inline tristate& operator=(bool boolValue); 0147 0148 inline tristate& operator=(tristate_cancelled_t); 0149 0150 friend inline bool operator==(bool boolValue, tristate tsValue); 0151 0152 friend inline bool operator==(tristate tsValue, bool boolValue); 0153 0154 friend inline bool operator!=(bool boolValue, tristate tsValue); 0155 0156 friend inline bool operator!=(tristate tsValue, bool boolValue); 0157 0158 friend inline bool operator==(tristate_cancelled_t, tristate tsValue); 0159 0160 friend inline bool operator==(tristate tsValue, tristate_cancelled_t); 0161 0162 friend inline bool operator!=(tristate_cancelled_t, tristate tsValue); 0163 0164 friend inline bool operator!=(tristate tsValue, tristate_cancelled_t); 0165 0166 friend inline bool operator==(tristate_cancelled_t, bool boolValue); 0167 0168 friend inline bool operator==(bool boolValue, tristate_cancelled_t); 0169 0170 friend inline bool operator!=(tristate_cancelled_t, bool boolValue); 0171 0172 friend inline bool operator!=(bool boolValue, tristate_cancelled_t); 0173 0174 friend inline QDebug operator<<(QDebug dbg, tristate tsValue); 0175 0176 /** 0177 * @return text representation of the value: "true", "false" or "cancelled". 0178 */ 0179 QString toString() const { 0180 if (m_value == False) { 0181 return QStringLiteral("false"); 0182 } 0183 return m_value == True ? QStringLiteral("true") : QStringLiteral("cancelled"); 0184 } 0185 0186 private: 0187 /** 0188 * @internal 0189 * States used internally. 0190 */ 0191 enum Value { 0192 False = 0, 0193 True = 1, 0194 Cancelled = 2 0195 }; 0196 0197 /** 0198 * @internal 0199 */ 0200 Value m_value; 0201 }; 0202 0203 tristate& tristate::operator=(tristate tsValue) 0204 { 0205 m_value = tsValue.m_value; 0206 return *this; 0207 } 0208 0209 tristate& tristate::operator=(bool boolValue) 0210 { 0211 m_value = boolValue ? True : False; 0212 return *this; 0213 } 0214 0215 tristate& tristate::operator=(tristate_cancelled_t) 0216 { 0217 m_value = Cancelled; 0218 return *this; 0219 } 0220 0221 /** 0222 * Inequality operator comparing a bool value @p boolValue and a tristate value @p tsValue. 0223 * 0224 * @return false if both @p boolValue and @p tsValue are true 0225 * or if both @p boolValue and @p tsValue are false. 0226 * Else, returns true. 0227 */ 0228 inline bool operator!=(bool boolValue, tristate tsValue) 0229 { 0230 return !((tsValue.m_value == tristate::True && boolValue) 0231 || (tsValue.m_value == tristate::False && !boolValue)); 0232 } 0233 0234 /** 0235 * Inequality operator comparing a tristate value @p tsValue and a bool value @p boolValue. 0236 * @see bool operator!=(bool boolValue, tristate tsValue) 0237 */ 0238 inline bool operator!=(tristate tsValue, bool boolValue) 0239 { 0240 return !((tsValue.m_value == tristate::True && boolValue) 0241 || (tsValue.m_value == tristate::False && !boolValue)); 0242 } 0243 0244 /** 0245 * Equality operator comparing a tristate value @p tsValue and a bool value @p boolValue. 0246 * @return true if 0247 * - both @p tsValue value and @p boolValue are true, or 0248 * - both @p tsValue value and @p boolValue are false 0249 * If the tristate value has value of cancelled, false is returned. 0250 */ 0251 inline bool operator==(tristate tsValue, bool boolValue) 0252 { 0253 return (tsValue.m_value == tristate::True && boolValue) 0254 || (tsValue.m_value == tristate::False && !boolValue); 0255 } 0256 0257 /** 0258 * Equality operator comparing a bool value @p boolValue and a tristate value @p tsValue. 0259 * @return true if both 0260 * - both @p tsValue value and @p boolValue are true, or 0261 * - both @p tsValue value and @p boolValue are false 0262 * If the tristate value has value of cancelled, false is returned. 0263 */ 0264 inline bool operator==(bool boolValue, tristate tsValue) 0265 { 0266 return (tsValue.m_value == tristate::True && boolValue) 0267 || (tsValue.m_value == tristate::False && !boolValue); 0268 } 0269 0270 /** 0271 * Equality operator comparing a cancelled and a tristate value @p tsValue. 0272 * @return true if @p tsValue is equal to cancelled value. 0273 */ 0274 inline bool operator==(tristate_cancelled_t, tristate tsValue) 0275 { 0276 return tsValue.m_value == tristate::Cancelled; 0277 } 0278 0279 /** 0280 * Equality operator comparing a cancelled and a tristate value @p tsValue. 0281 * @return true if @p tsValue is equal to cancelled value. 0282 */ 0283 inline bool operator==(tristate tsValue, tristate_cancelled_t) 0284 { 0285 return tsValue.m_value == tristate::Cancelled; 0286 } 0287 0288 /** 0289 * Equality operator comparing a cancelled and a bool value. 0290 * @return false. 0291 */ 0292 inline bool operator==(tristate_cancelled_t, bool) 0293 { 0294 return false; 0295 } 0296 0297 /** 0298 * Equality operator comparing a cancelled and a bool value. 0299 * @return false. 0300 */ 0301 inline bool operator==(bool, tristate_cancelled_t) 0302 { 0303 return false; 0304 } 0305 0306 /** 0307 * Inequality operator comparing a cancelled and a tristate value @p tsValue. 0308 * @return true if @p tsValue is not equal to cancelled value. 0309 */ 0310 inline bool operator!=(tristate_cancelled_t, tristate tsValue) 0311 { 0312 return tsValue.m_value != tristate::Cancelled; 0313 } 0314 0315 /** 0316 * Equality operator comparing a cancelled and a tristate value @p tsValue. 0317 * @return true if @p tsValue is not equal to cancelled value. 0318 */ 0319 inline bool operator!=(tristate tsValue, tristate_cancelled_t) 0320 { 0321 return tsValue.m_value != tristate::Cancelled; 0322 } 0323 0324 /** 0325 * Equality operator comparing a cancelled and a bool value. 0326 * @return true. 0327 */ 0328 inline bool operator!=(tristate_cancelled_t, bool) 0329 { 0330 return true; 0331 } 0332 0333 /** 0334 * Equality operator comparing a cancelled and a bool value. 0335 * @return true. 0336 */ 0337 inline bool operator!=(bool, tristate_cancelled_t) 0338 { 0339 return true; 0340 } 0341 0342 //! qDebug() stream operator. Writes tristate value to the debug output in a nicely formatted way. 0343 inline QDebug operator<<(QDebug dbg, tristate tsValue) 0344 { 0345 switch (tsValue.m_value) { 0346 case tristate::True: dbg.nospace() << "true"; break; 0347 case tristate::False: dbg.nospace() << "false"; break; 0348 case tristate::Cancelled: dbg.nospace() << "cancelled"; break; 0349 } 0350 return dbg.space(); 0351 } 0352 0353 inline QDebug operator<<(QDebug dbg, tristate_cancelled_t) 0354 { 0355 dbg.nospace() << "cancelled"; 0356 return dbg.space(); 0357 } 0358 0359 inline bool operator~(tristate_cancelled_t) 0360 { 0361 return true; 0362 } 0363 0364 inline bool operator!(tristate_cancelled_t) 0365 { 0366 return false; 0367 } 0368 0369 #endif