File indexing completed on 2024-12-08 10:15:15
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003-2019 Jarosław Staniek <staniek@kde.org> 0003 0004 Portions of kstandarddirs.cpp: 0005 Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org> 0006 Copyright (C) 1999,2007 Stephan Kulow <coolo@kde.org> 0007 Copyright (C) 1999 Waldo Bastian <bastian@kde.org> 0008 Copyright (C) 2009 David Faure <faure@kde.org> 0009 0010 This program is free software; you can redistribute it and/or 0011 modify it under the terms of the GNU Library General Public 0012 License as published by the Free Software Foundation; either 0013 version 2 of the License, or (at your option) any later version. 0014 0015 This program is distributed in the hope that it will be useful, 0016 but WITHOUT ANY WARRANTY; without even the implied warranty of 0017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0018 Library General Public License for more details. 0019 0020 You should have received a copy of the GNU Library General Public License 0021 along with this program; see the file COPYING. If not, write to 0022 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0023 * Boston, MA 02110-1301, USA. 0024 */ 0025 0026 #ifndef KDB_TOOLS_UTILS_H 0027 #define KDB_TOOLS_UTILS_H 0028 0029 #include "kdb_export.h" 0030 #include "config-kdb.h" 0031 0032 #include <QObject> 0033 #include <QDateTime> 0034 #include <QMetaMethod> 0035 #include <QDebug> 0036 0037 namespace KDbUtils 0038 { 0039 0040 //! @return true if @a o has parent @a par (checks recursively) 0041 KDB_EXPORT bool hasParent(QObject* par, QObject* o); 0042 0043 //! @return parent object of @a o that is of type @a type or @c nullptr if no such parent 0044 template<class type> 0045 inline type findParent(QObject* o, const char* className = nullptr) 0046 { 0047 if (!o) 0048 return nullptr; 0049 while ((o = o->parent())) { 0050 if (::qobject_cast< type >(o) && (!className || o->inherits(className))) 0051 return ::qobject_cast< type >(o); 0052 } 0053 return nullptr; 0054 } 0055 0056 /** 0057 * Returns the time as a string using Qt::ISODateWithMs format 0058 * 0059 * If milliseconds is zero then they are not appended. 0060 * Works also for Qt < 5.8 which does not offer QTime::toString(Qt::ISODateWithMs). 0061 * 0062 * @since 3.2 0063 */ 0064 KDB_EXPORT QString toISODateStringWithMs(const QTime &time); 0065 0066 /** 0067 * Returns the date/time as a string using Qt::ISODateWithMs format 0068 * 0069 * If milliseconds in time is zero then they are not appended. 0070 * Works also for Qt < 5.8 which does not offer QDateTime::toString(Qt::ISODateWithMs). 0071 * 0072 * @since 3.2 0073 */ 0074 KDB_EXPORT QString toISODateStringWithMs(const QDateTime &dateTime); 0075 0076 /** 0077 * Returns the time represented by the string using the Qt::ISODateWithMs format 0078 * 0079 * Milliseconds are optional. 0080 * Works also for Qt < 5.8 which does not offer QTime::fromString(QString, Qt::ISODateWithMs). 0081 * 0082 * @note Equal to QTime::fromString(string, Qt::ISODate) since the Qt::ISODate mode already 0083 * supports milliseconds in case of fromString(). 0084 * 0085 * @since 3.2 0086 */ 0087 KDB_EXPORT QTime timeFromISODateStringWithMs(const QString &string); 0088 0089 /** 0090 * Returns the date/time represented by the string using the Qt::ISODateWithMs format 0091 * 0092 * Milliseconds of time are optional. 0093 * Works also for Qt < 5.8 which does not offer QDateTime::fromString(QString, Qt::ISODateWithMs). 0094 * 0095 * @note Equal to QDateTime::fromString(string, Qt::ISODate) since the Qt::ISODate mode already 0096 * supports milliseconds in case of fromString(). 0097 * 0098 * @since 3.2 0099 */ 0100 KDB_EXPORT QDateTime dateTimeFromISODateStringWithMs(const QString &string); 0101 0102 //! QDateTime - a hack needed because QVariant(QTime) has broken isNull() 0103 KDB_EXPORT QDateTime stringToHackedQTime(const QString& s); 0104 0105 /*! Serializes @a map to the array pointed by @a array. 0106 KDbUtils::deserializeMap() can be used to deserialize this array back to map. 0107 Does nothing if @a array is @c nullptr. */ 0108 KDB_EXPORT void serializeMap(const QMap<QString, QString>& map, QByteArray *array); 0109 0110 /*! Serializes @a map to the string pointed by @a string. 0111 KDbUtils::deserializeMap() can be used to deserialize this array back to map. 0112 Does nothing if @a string is @c nullptr. */ 0113 KDB_EXPORT void serializeMap(const QMap<QString, QString>& map, QString *string); 0114 0115 /*! @return a map deserialized from a byte array @a array. 0116 @a array need to contain data previously serialized using KexiUtils::serializeMap(). */ 0117 KDB_EXPORT QMap<QString, QString> deserializeMap(const QByteArray& array); 0118 0119 /*! @return a map deserialized from @a string. 0120 @a string need to contain data previously serialized using KexiUtils::serializeMap(). */ 0121 KDB_EXPORT QMap<QString, QString> deserializeMap(const QString& string); 0122 0123 /** 0124 * Returns a valid filename converted from given string 0125 * 0126 * Following steps are performed: 0127 * - replace \\, /, :, *, ?, ", <, >, |, \n \\t characters with a space, 0128 * - simplify whitespace by removing redundant space characters using QString::simplified(). 0129 * - prepend '_' character if the first character is '.', so the file will not be considered hidden 0130 * (since 3.2.0). 0131 * 0132 * @note Do not pass full paths here but only filename strings. 0133 */ 0134 KDB_EXPORT QString stringToFileName(const QString& string); 0135 0136 /*! Performs a simple @a string encryption using rot47-like algorithm. 0137 Each character's unicode value is increased by 47 + i (where i is index of the character). 0138 The resulting string still contains readable characters but some of them can be non-ASCII. 0139 Does nothing if @a string is @c nullptr. 0140 @note Do not use this for data that can be accessed by attackers! */ 0141 KDB_EXPORT void simpleCrypt(QString *string); 0142 0143 /*! Performs a simple @a string decryption using rot47-like algorithm, 0144 using opposite operations to KexiUtils::simpleCrypt(). 0145 @return true on success and false on failure. Failue means that one or more characters have unicode 0146 numbers smaller than value of 47 + i. On failure @a string is not altered. 0147 Does nothing and returns @c false if @a string is @c nullptr. 0148 */ 0149 KDB_EXPORT bool simpleDecrypt(QString *string); 0150 0151 //! @internal 0152 KDB_EXPORT QString pointerToStringInternal(void* pointer, int size); 0153 //! @internal 0154 KDB_EXPORT void* stringToPointerInternal(const QString& string, int size); 0155 0156 //! @return a pointer @a pointer safely serialized to string 0157 template<class type> 0158 QString pointerToString(type *pointer) 0159 { 0160 return pointerToStringInternal(pointer, sizeof(type*)); 0161 } 0162 0163 //! @return a pointer of type @a type safely deserialized from @a string 0164 template<class type> 0165 type* stringToPointer(const QString& string) 0166 { 0167 return static_cast<type*>(stringToPointerInternal(string, sizeof(type*))); 0168 } 0169 0170 //! @return value converted to text, squeezed to reasonable length, useful for debugging 0171 //! If the value is not a byte array or string, or if it's not longer than 1024 characters, 0172 //! @a value is returned. 0173 //! @since 3.1 0174 KDB_EXPORT QVariant squeezedValue(const QVariant &value); 0175 0176 //! @short Autodeleting hash 0177 template <class Key, class T> 0178 class AutodeletedHash : public QHash<Key, T> 0179 { 0180 public: 0181 //! Creates autodeleting hash as a copy of @a other. 0182 //! Auto-deletion is not enabled as it would cause double deletion for items. 0183 //! If you enable auto-deletion on here, make sure you disable it in the @a other hash. 0184 AutodeletedHash(const AutodeletedHash& other) : QHash<Key, T>(other), m_autoDelete(false) {} 0185 0186 //! Creates empty autodeleting hash. 0187 //! Auto-deletion is enabled by default. 0188 AutodeletedHash(bool autoDelete = true) : QHash<Key, T>(), m_autoDelete(autoDelete) {} 0189 0190 ~AutodeletedHash() { 0191 if (m_autoDelete) { 0192 qDeleteAll(*this); 0193 } 0194 } 0195 void setAutoDelete(bool set) { 0196 m_autoDelete = set; 0197 } 0198 bool autoDelete() const { 0199 return m_autoDelete; 0200 } 0201 void clear() { 0202 if (m_autoDelete) { 0203 qDeleteAll(*this); 0204 } 0205 QHash<Key, T>::clear(); 0206 } 0207 typename QHash<Key, T>::iterator erase(typename QHash<Key, T>::iterator pos) { 0208 typename QHash<Key, T>::iterator it = QHash<Key, T>::erase(pos); 0209 if (m_autoDelete) { 0210 delete it.value(); 0211 it.value() = 0; 0212 return it; 0213 } 0214 } 0215 typename QHash<Key, T>::iterator insert(const Key &key, const T &value) { 0216 if (m_autoDelete) { 0217 T &oldValue = QHash<Key, T>::operator[](key); 0218 if (oldValue && oldValue != value) { // only delete if differs 0219 delete oldValue; 0220 } 0221 } 0222 return QHash<Key, T>::insert(key, value); 0223 } 0224 int remove(const Key &key) { 0225 if (m_autoDelete) { 0226 const QList<T> values(QHash<Key, T>::values(key)); 0227 const int result = QHash<Key, T>::remove(key); 0228 for (T item : values) { 0229 delete item; 0230 } 0231 return result; 0232 } else { 0233 return QHash<Key, T>::remove(key); 0234 } 0235 } 0236 // note: no need to override insertMulti(), unite(), take(), they do not replace items 0237 0238 private: 0239 bool m_autoDelete; 0240 }; 0241 0242 //! @short Autodeleting list 0243 template <typename T> 0244 class AutodeletedList : public QList<T> 0245 { 0246 public: 0247 //! Creates autodeleting list as a copy of @a other. 0248 //! Auto-deletion is not enabled as it would cause double deletion for items. 0249 //! If you enable auto-deletion on here, make sure you disable it in the @a other list. 0250 AutodeletedList(const AutodeletedList& other) 0251 : QList<T>(other), m_autoDelete(false) {} 0252 0253 //! Creates empty autodeleting list. 0254 //! Auto-deletion is enabled by default. 0255 AutodeletedList(bool autoDelete = true) : QList<T>(), m_autoDelete(autoDelete) {} 0256 0257 ~AutodeletedList() { 0258 if (m_autoDelete) qDeleteAll(*this); 0259 } 0260 void setAutoDelete(bool set) { 0261 m_autoDelete = set; 0262 } 0263 bool autoDelete() const { 0264 return m_autoDelete; 0265 } 0266 void removeAt(int i) { 0267 T item = QList<T>::takeAt(i); if (m_autoDelete) delete item; 0268 } 0269 void removeFirst() { 0270 T item = QList<T>::takeFirst(); if (m_autoDelete) delete item; 0271 } 0272 void removeLast() { 0273 T item = QList<T>::takeLast(); if (m_autoDelete) delete item; 0274 } 0275 void replace(int i, const T& value) { 0276 T item = QList<T>::takeAt(i); insert(i, value); if (m_autoDelete) delete item; 0277 } 0278 void insert(int i, const T& value) { 0279 QList<T>::insert(i, value); 0280 } 0281 typename QList<T>::iterator erase(typename QList<T>::iterator pos) { 0282 T item = *pos; 0283 typename QList<T>::iterator res = QList<T>::erase(pos); 0284 if (m_autoDelete) 0285 delete item; 0286 return res; 0287 } 0288 typename QList<T>::iterator erase( 0289 typename QList<T>::iterator afirst, 0290 typename QList<T>::iterator alast) { 0291 if (!m_autoDelete) 0292 return QList<T>::erase(afirst, alast); 0293 while (afirst != alast) { 0294 T item = *afirst; 0295 afirst = QList<T>::erase(afirst); 0296 delete item; 0297 } 0298 return alast; 0299 } 0300 void pop_back() { 0301 removeLast(); 0302 } 0303 void pop_front() { 0304 removeFirst(); 0305 } 0306 int removeAll(const T& value) { 0307 if (!m_autoDelete) 0308 return QList<T>::removeAll(value); 0309 typename QList<T>::iterator it(QList<T>::begin()); 0310 int removedCount = 0; 0311 while (it != QList<T>::end()) { 0312 if (*it == value) { 0313 T item = *it; 0314 it = QList<T>::erase(it); 0315 delete item; 0316 removedCount++; 0317 } else 0318 ++it; 0319 } 0320 return removedCount; 0321 } 0322 void clear() { 0323 if (!m_autoDelete) 0324 return QList<T>::clear(); 0325 while (!QList<T>::isEmpty()) { 0326 T item = QList<T>::takeFirst(); 0327 delete item; 0328 } 0329 } 0330 0331 private: 0332 bool m_autoDelete; 0333 }; 0334 0335 //! @short Case insensitive hash container supporting QString or QByteArray keys. 0336 //! Keys are turned to lowercase before inserting. 0337 template <typename Key, typename T> 0338 class CaseInsensitiveHash : public QHash<Key, T> 0339 { 0340 public: 0341 CaseInsensitiveHash() : QHash<Key, T>() {} 0342 typename QHash<Key, T>::iterator find(const Key& key) const { 0343 return QHash<Key, T>::find(key.toLower()); 0344 } 0345 typename QHash<Key, T>::const_iterator constFind(const Key& key) const { 0346 return QHash<Key, T>::constFind(key.toLower()); 0347 } 0348 bool contains(const Key& key) const { 0349 return QHash<Key, T>::contains(key.toLower()); 0350 } 0351 int count(const Key& key) const { 0352 return QHash<Key, T>::count(key.toLower()); 0353 } 0354 typename QHash<Key, T>::iterator insert(const Key& key, const T& value) { 0355 return QHash<Key, T>::insert(key.toLower(), value); 0356 } 0357 typename QHash<Key, T>::iterator insertMulti(const Key& key, const T& value) { 0358 return QHash<Key, T>::insertMulti(key.toLower(), value); 0359 } 0360 const Key key(const T& value, const Key& defaultKey) const { 0361 return QHash<Key, T>::key(value, defaultKey.toLower()); 0362 } 0363 int remove(const Key& key) { 0364 return QHash<Key, T>::remove(key.toLower()); 0365 } 0366 const T take(const Key& key) { 0367 return QHash<Key, T>::take(key.toLower()); 0368 } 0369 const T value(const Key& key) const { 0370 return QHash<Key, T>::value(key.toLower()); 0371 } 0372 const T value(const Key& key, const T& defaultValue) const { 0373 return QHash<Key, T>::value(key.toLower(), defaultValue); 0374 } 0375 QList<T> values(const Key& key) const { 0376 return QHash<Key, T>::values(key.toLower()); 0377 } 0378 T& operator[](const Key& key) { 0379 return QHash<Key, T>::operator[](key.toLower()); 0380 } 0381 const T operator[](const Key& key) const { 0382 return QHash<Key, T>::operator[](key.toLower()); 0383 } 0384 }; 0385 0386 //! A set created from static (0-terminated) array of raw null-terminated strings. 0387 class KDB_EXPORT StaticSetOfStrings 0388 { 0389 public: 0390 StaticSetOfStrings(); 0391 explicit StaticSetOfStrings(const char* const array[]); 0392 ~StaticSetOfStrings(); 0393 void setStrings(const char* const array[]); 0394 bool isEmpty() const; 0395 0396 //! @return true if @a string can be found within set, comparison is case sensitive 0397 bool contains(const QByteArray& string) const; 0398 private: 0399 class Private; 0400 Private * const d; 0401 Q_DISABLE_COPY(StaticSetOfStrings) 0402 }; 0403 0404 /*! @return debugging string for object @a object of type @a T */ 0405 template <typename T> 0406 QString debugString(const T& object) 0407 { 0408 QString result; 0409 QDebug dbg(&result); 0410 dbg << object; 0411 return result; 0412 } 0413 0414 //! Used by findExe(). 0415 enum class FindExeOption { 0416 //! No options 0417 None = 0, 0418 //! If set, the path returned may not have the executable bit set. 0419 IgnoreExecBit = 1 0420 }; 0421 Q_DECLARE_FLAGS(FindExeOptions, FindExeOption) 0422 0423 /** 0424 * Finds the executable in the system path. 0425 * 0426 * A valid executable must be a file and have its executable bit set. 0427 * 0428 * @param appname The name of the executable file for which to search. 0429 * if this contains a path separator, it will be resolved 0430 * according to the current working directory 0431 * (shell-like behavior). 0432 * @param path The path which will be searched. If this is 0433 * null (default), the @c $PATH environment variable will 0434 * be searched. 0435 * @param options Options, see FindExeOption. 0436 * 0437 * @return The path of the executable. If it was not found, returns QString(). 0438 */ 0439 QString findExe(const QString& appname, 0440 const QString& path = QString(), 0441 FindExeOptions options = FindExeOption::None); 0442 0443 //! A single property 0444 //! @note This property is general-purpose and not related to Qt Properties. 0445 //! @see KDbUtils::PropertySet 0446 class KDB_EXPORT Property { 0447 public: 0448 //! Constructs a null property 0449 Property(); 0450 0451 Property(const QVariant &aValue, const QString &aCaption); 0452 0453 Property(const Property &other); 0454 0455 ~Property(); 0456 0457 bool operator==(const Property &other) const; 0458 0459 bool operator!=(const Property &other) const { return !operator==(other); } 0460 0461 bool isNull() const; 0462 0463 QVariant value() const; 0464 0465 void setValue(const QVariant &value); 0466 0467 QString caption() const; 0468 0469 void setCaption(const QString &caption); 0470 0471 private: 0472 class Private; 0473 Private * const d; 0474 }; 0475 0476 //! A set of properties. 0477 //! @note These properties are general-purpose and not related to Qt Properties. 0478 //! @see KDbUtils::Property 0479 class KDB_EXPORT PropertySet 0480 { 0481 public: 0482 PropertySet(); 0483 0484 PropertySet(const PropertySet &other); 0485 0486 ~PropertySet(); 0487 0488 //! Assigns @a other to this property set and returns a reference to this property set. 0489 PropertySet& operator=(const PropertySet &other); 0490 0491 //! @return true if this property set has exactly the same properties as @a other 0492 //! @since 3.1 0493 bool operator==(const PropertySet &other) const; 0494 0495 //! @return true if this property differs in at least one property from @a other 0496 //! @since 3.1 0497 bool operator!=(const PropertySet &other) const { return !operator==(other); } 0498 0499 //! Inserts property with a given @a name, @a value and @a caption. 0500 //! If @a caption is empty, caption from existing property is reused. 0501 //! @a name must be a valid identifier (see KDb::isIdentifier()). 0502 void insert(const QByteArray &name, const QVariant &value, const QString &caption = QString()); 0503 0504 //! Sets caption for property @a name to @a caption. 0505 //! If such property does not exist, does nothing. 0506 //! @since 3.1 0507 void setCaption(const QByteArray &name, const QString &caption); 0508 0509 //! Sets value for property @a name to @a value. 0510 //! If such property does not exist, does nothing. 0511 //! @since 3.1 0512 void setValue(const QByteArray &name, const QVariant &value); 0513 0514 //! Removes property with a given @a name. 0515 void remove(const QByteArray &name); 0516 0517 //! @return property with a given @a name. 0518 //! If not found, a null Property is returned (Property::isNull). 0519 Property property(const QByteArray &name) const; 0520 0521 //! @return a list of property names. 0522 QList<QByteArray> names() const; 0523 0524 private: 0525 class Private; 0526 Private * const d; 0527 }; 0528 0529 } // KDbUtils 0530 0531 #endif //KDB_TOOLS_UTILS_H