KDb

KDbUtils.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003-2019 Jarosław Staniek <staniek@kde.org>
3
4 Portions of kstandarddirs.cpp:
5 Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
6 Copyright (C) 1999,2007 Stephan Kulow <coolo@kde.org>
7 Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
8 Copyright (C) 2009 David Faure <faure@kde.org>
9
10 Portions of kshell.cpp:
11 Copyright (c) 2003,2007 Oswald Buddenhagen <ossi@kde.org>
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Library General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Library General Public License for more details.
22
23 You should have received a copy of the GNU Library General Public License
24 along with this program; see the file COPYING. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 * Boston, MA 02110-1301, USA.
27*/
28
29#include "KDbUtils.h"
30#include "KDb.h"
31#include "KDbConnection.h"
32#include "KDbDriverManager.h"
33#include "KDbUtils_p.h"
34#include "config-kdb.h"
35#include "kdb_debug.h"
36
37#include <QRegularExpression>
38#include <QDataStream>
39#include <QDir>
40#include <QFile>
41#include <QFileInfo>
42
43static const int SQUEEZED_TEXT_LIMIT = 1024;
44static const int SQUEEZED_TEXT_SUFFIX = 24;
45
46#ifdef Q_OS_WIN
47#include <windows.h>
48#ifdef _WIN32_WCE
49#include <basetyps.h>
50#endif
51#ifdef Q_OS_WIN64
52//! @todo did not find a reliable way to fix with kdewin mingw header
53#define interface struct
54#endif
55#endif
56
57using namespace KDbUtils;
58
59class Q_DECL_HIDDEN Property::Private
60{
61public:
62 Private() : isNull(true) {}
63 Private(const QVariant &aValue, const QString &aCaption)
64 : value(aValue), caption(aCaption), isNull(false)
65 {
66 }
67 bool operator==(const Private &other) const {
68 return std::tie(value, caption, isNull) == std::tie(other.value, other.caption, other.isNull);
69 }
70 QVariant value; //!< Property value
71 QString caption; //!< User visible property caption
72 bool isNull;
73};
74
76 : d(new Private)
77{
78}
79
80Property::Property(const QVariant &value, const QString &caption)
81 : d(new Private(value, caption))
82{
83}
84
85Property::Property(const Property &other)
86: d(new Private(*other.d))
87{
88}
89
90Property::~Property()
91{
92 delete d;
93}
94
95bool Property::operator==(const Property &other) const
96{
97 return *d == *other.d;
98}
99
100bool Property::isNull() const
101{
102 return d->isNull;
103}
104
105QVariant Property::value() const
106{
107 return d->value;
108}
109
110void Property::setValue(const QVariant &value)
111{
112 d->value = value;
113 d->isNull = false;
114}
115
116QString Property::caption() const
117{
118 return d->caption;
119}
120
121void Property::setCaption(const QString &caption)
122{
123 d->caption = caption;
124 d->isNull = false;
125}
126
127//---------
128
129bool KDbUtils::hasParent(QObject *par, QObject *o)
130{
131 if (!o || !par) {
132 return false;
133 }
134 while (o && o != par) {
135 o = o->parent();
136 }
137 return o == par;
138}
139
140QString KDbUtils::toISODateStringWithMs(const QTime& time)
141{
142#ifdef HAVE_QT_ISODATEWITHMS
143 return time.toString(Qt::ISODateWithMs);
144#else
145 QString result;
146 if (time.isValid()) {
147 result = QString::asprintf("%02d:%02d:%02d.%03d", time.hour(), time.minute(), time.second(),
148 time.msec());
149 }
150 return result;
151#endif
152}
153
154QString KDbUtils::toISODateStringWithMs(const QDateTime& dateTime)
155{
156#ifdef HAVE_QT_ISODATEWITHMS
157 return dateTime.toString(Qt::ISODateWithMs);
158#else
159 QString result;
160 if (!dateTime.isValid()) {
161 return result;
162 }
163 result = dateTime.toString(Qt::ISODate);
164 if (result.isEmpty()) { // failure
165 return result;
166 }
167 QString timeString = KDbUtils::toISODateStringWithMs(dateTime.time());
168 if (timeString.isEmpty()) { // failure
169 return QString();
170 }
171 const int offset = strlen("0000-00-00T");
172 const int timeLen = strlen("00:00:00");
173 result.replace(offset, timeLen, timeString); // replace time with time+ms
174 return result;
175#endif
176}
177
178QTime KDbUtils::timeFromISODateStringWithMs(const QString &string)
179{
180#ifdef HAVE_QT_ISODATEWITHMS
181 return QTime::fromString(string, Qt::ISODateWithMs);
182#else
183 return QTime::fromString(string, Qt::ISODate); // supports HH:mm:ss.zzzzz already
184#endif
185}
186
187QDateTime KDbUtils::dateTimeFromISODateStringWithMs(const QString &string)
188{
189#ifdef HAVE_QT_ISODATEWITHMS
191#else
192 return QDateTime::fromString(string, Qt::ISODate); // supports HH:mm:ss.zzzzz already
193#endif
194}
195
196QDateTime KDbUtils::stringToHackedQTime(const QString &s)
197{
198 if (s.isEmpty()) {
199 return QDateTime();
200 }
201 return QDateTime(QDate(0, 1, 2), KDbUtils::timeFromISODateStringWithMs(s));
202}
203
204void KDbUtils::serializeMap(const QMap<QString, QString>& map, QByteArray *array)
205{
206 if (!array) {
207 return;
208 }
210 ds.setVersion(QDataStream::Qt_3_1);
211 ds << map;
212}
213
214void KDbUtils::serializeMap(const QMap<QString, QString>& map, QString *string)
215{
216 if (!string) {
217 return;
218 }
219 QByteArray array;
221 ds.setVersion(QDataStream::Qt_3_1);
222 ds << map;
223 kdbDebug() << array[3] << array[4] << array[5];
224 const int size = array.size();
225 string->clear();
226 string->reserve(size);
227 for (int i = 0; i < size; i++) {
228 (*string)[i] = QChar(ushort(array[i]) + 1);
229 }
230}
231
232QMap<QString, QString> KDbUtils::deserializeMap(const QByteArray& array)
233{
235 QByteArray ba(array);
237 ds.setVersion(QDataStream::Qt_3_1);
238 ds >> map;
239 return map;
240}
241
242QMap<QString, QString> KDbUtils::deserializeMap(const QString& string)
243{
244 QByteArray array;
245 const int size = string.length();
246 array.resize(size);
247 for (int i = 0; i < size; i++) {
248 array[i] = char(string[i].unicode() - 1);
249 }
252 ds.setVersion(QDataStream::Qt_3_1);
253 ds >> map;
254 return map;
255}
256
257QString KDbUtils::stringToFileName(const QString& string)
258{
259 QString _string(string);
260 static const QRegularExpression re(QLatin1String("[\\\\/:\\*?\"<>|]"));
261 _string.replace(re, QLatin1String(" "));
262 if (_string.startsWith(QLatin1Char('.'))) {
263 _string.prepend(QLatin1Char('_'));
264 }
265 return _string.simplified();
266}
267
268void KDbUtils::simpleCrypt(QString *string)
269{
270 if (!string) {
271 return;
272 }
273 for (int i = 0; i < string->length(); i++) {
274 ushort& unicode = (*string)[i].unicode();
275 unicode += (47 + i);
276 }
277}
278
279bool KDbUtils::simpleDecrypt(QString *string)
280{
281 if (!string) {
282 return false;
283 }
284 QString result(*string);
285 for (int i = 0; i < result.length(); i++) {
286 ushort& unicode = result[i].unicode();
287 if (unicode <= (47 + i)) {
288 return false;
289 }
290 unicode -= (47 + i);
291 }
292 *string = result;
293 return true;
294}
295
296QString KDbUtils::pointerToStringInternal(void* pointer, int size)
297{
298 QString string;
299 unsigned char* cstr_pointer = (unsigned char*) & pointer;
300 for (int i = 0; i < size; i++) {
301 QString s;
302 s.asprintf("%2.2x", cstr_pointer[i]);
303 string.append(s);
304 }
305 return string;
306}
307
308void* KDbUtils::stringToPointerInternal(const QString& string, int size)
309{
310 if ((string.length() / 2) < size)
311 return nullptr;
312 QByteArray array;
313 array.resize(size);
314 bool ok;
315 for (int i = 0; i < size; i++) {
316 array[i] = (unsigned char)(string.midRef(i * 2, 2).toUInt(&ok, 16));
317 if (!ok)
318 return nullptr;
319 }
320 return static_cast<void*>(array.data());
321}
322
323//---------
324
325//! @internal
326class Q_DECL_HIDDEN StaticSetOfStrings::Private
327{
328public:
329 Private() : array(nullptr), set(nullptr) {}
330 ~Private() {
331 delete set;
332 }
333 const char* const * array;
334 QSet<QByteArray> *set;
335};
336
337StaticSetOfStrings::StaticSetOfStrings()
338 : d(new Private)
339{
340}
341
342StaticSetOfStrings::StaticSetOfStrings(const char* const array[])
343 : d(new Private)
344{
345 setStrings(array);
346}
347
348StaticSetOfStrings::~StaticSetOfStrings()
349{
350 delete d;
351}
352
353void StaticSetOfStrings::setStrings(const char* const array[])
354{
355 delete d->set;
356 d->set = nullptr;
357 d->array = array;
358}
359
360bool StaticSetOfStrings::isEmpty() const
361{
362 return d->array == nullptr;
363}
364
366{
367 if (!d->set) {
368 d->set = new QSet<QByteArray>();
369 for (const char * const * p = d->array;*p;p++)
370 d->set->insert(QByteArray::fromRawData(*p, qstrlen(*p)));
371 }
372 return d->set->contains(string);
373}
374
375//---------
376
377#ifdef Q_OS_MACOS
378//! Internal, from kdelibs' kstandarddirs.cpp
379static QString getBundle(const QString& path, bool ignore)
380{
381 QFileInfo info;
382 QString bundle = path;
383 bundle += QLatin1String(".app/Contents/MacOS/") + bundle.section(QLatin1Char('/'), -1);
384 info.setFile( bundle );
385 FILE *file;
386 if (file = fopen(info.absoluteFilePath().toUtf8().constData(), "r")) {
387 fclose(file);
388 struct stat _stat;
389 if ((stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
390 return QString();
391 }
392 if ( ignore || (_stat.st_mode & S_IXUSR) ) {
393 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
394 return bundle;
395 }
396 }
397 }
398 return QString();
399}
400#endif
401
402//! Internal, from kdelibs' kstandarddirs.cpp
403static QString checkExecutable(const QString& path, bool ignoreExecBit)
404{
405#ifdef Q_OS_MACOS
406 QString bundle = getBundle(path, ignoreExecBit);
407 if (!bundle.isEmpty()) {
408 return bundle;
409 }
410#endif
411 QFileInfo info(path);
412 QFileInfo orig = info;
413#ifdef Q_OS_MACOS
414 FILE *file;
415 if (file = fopen(orig.absoluteFilePath().toUtf8().constData(), "r")) {
416 fclose(file);
417 struct stat _stat;
418 if ((stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
419 return QString();
420 }
421 if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
422 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
423 orig.makeAbsolute();
424 return orig.filePath();
425 }
426 }
427 }
428 return QString();
429#else
430 if (info.exists() && info.isSymLink())
431 info = QFileInfo(info.canonicalFilePath());
432 if (info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile()) {
433 // return absolute path, but without symlinks resolved in order to prevent
434 // problems with executables that work differently depending on name they are
435 // run as (for example gunzip)
436 orig.makeAbsolute();
437 return orig.filePath();
438 }
439 return QString();
440#endif
441}
442
443//! Internal, from kdelibs' kstandarddirs.cpp
444#if defined _WIN32 || defined _WIN64
445# define KPATH_SEPARATOR ';'
446# define ESCAPE '^'
447#else
448# define KPATH_SEPARATOR ':'
449# define ESCAPE '\\'
450#endif
451
452//! Internal, from kdelibs' kstandarddirs.cpp
453static inline QString equalizePath(QString &str)
454{
455#ifdef Q_OS_WIN
456 // filter pathes through QFileInfo to have always
457 // the same case for drive letters
458 QFileInfo f(str);
459 if (f.isAbsolute())
460 return f.absoluteFilePath();
461 else
462#endif
463 return str;
464}
465
466//! Internal, from kdelibs' kstandarddirs.cpp
467static void tokenize(QStringList& tokens, const QString& str,
468 const QString& delim)
469{
470 const int len = str.length();
471 QString token;
472
473 for(int index = 0; index < len; index++) {
474 if (delim.contains(str[index])) {
475 tokens.append(equalizePath(token));
476 token.clear();
477 } else {
478 token += str[index];
479 }
480 }
481 if (!token.isEmpty()) {
482 tokens.append(equalizePath(token));
483 }
484}
485
486//! Internal, based on kdelibs' kshell.cpp
487static QString tildeExpand(const QString &fname)
488{
489 if (!fname.isEmpty() && fname[0] == QLatin1Char('~')) {
490 int pos = fname.indexOf( QLatin1Char('/') );
491 QString ret = QDir::homePath(); // simplified
492 if (pos > 0) {
493 ret += fname.midRef(pos);
494 }
495 return ret;
496 } else if (fname.length() > 1 && fname[0] == QLatin1Char(ESCAPE) && fname[1] == QLatin1Char('~')) {
497 return fname.mid(1);
498 }
499 return fname;
500}
501
502//! Internal, from kdelibs' kstandarddirs.cpp
503static QStringList systemPaths(const QString& pstr)
504{
505 QStringList tokens;
506 QString p = pstr;
507
508 if (p.isEmpty()) {
509 p = QString::fromLocal8Bit( qgetenv( "PATH" ) );
510 }
511
512 QString delimiters(QLatin1Char(KPATH_SEPARATOR));
513 delimiters += QLatin1Char('\b');
514 tokenize(tokens, p, delimiters);
515
516 QStringList exePaths;
517
518 // split path using : or \b as delimiters
519 for(int i = 0; i < tokens.count(); i++) {
520 exePaths << tildeExpand(tokens[ i ]);
521 }
522 return exePaths;
523}
524
525//! Internal, from kdelibs' kstandarddirs.cpp
526#ifdef Q_OS_WIN
527static QStringList executableExtensions()
528{
529 QStringList ret = QString::fromLocal8Bit(qgetenv("PATHEXT")).split(QLatin1Char(';'));
530 if (!ret.contains(QLatin1String(".exe"), Qt::CaseInsensitive)) {
531 // If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
532 ret.clear();
533 ret << QLatin1String(".exe")
534 << QLatin1String(".com")
535 << QLatin1String(".bat")
536 << QLatin1String(".cmd");
537 }
538 return ret;
539}
540#endif
541
542//! Based on kdelibs' kstandarddirs.cpp
543QString KDbUtils::findExe(const QString& appname,
544 const QString& path,
545 FindExeOptions options)
546{
547#ifdef Q_OS_WIN
548 QStringList executable_extensions = executableExtensions();
549 if (!executable_extensions.contains(
552 {
553 QString found_exe;
554 foreach (const QString& extension, executable_extensions) {
555 found_exe = findExe(appname + extension, path, options);
556 if (!found_exe.isEmpty()) {
557 return found_exe;
558 }
559 }
560 return QString();
561 }
562#endif
563
564 // absolute or relative path?
565 if (appname.contains(QDir::separator())) {
566 return checkExecutable(appname, options & FindExeOption::IgnoreExecBit);
567 }
568
569 QString p;
570 QString result;
571
572 const QStringList exePaths = systemPaths(path);
573 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
574 {
575 p = (*it) + QLatin1Char('/');
576 p += appname;
577
578 // Check for executable in this tokenized path
579 result = checkExecutable(p, options & FindExeOption::IgnoreExecBit);
580 if (!result.isEmpty()) {
581 return result;
582 }
583 }
584
585 // Not found in PATH, look into a bin dir
586 p = QFile::decodeName(BIN_INSTALL_DIR "/");
587 p += appname;
588 result = checkExecutable(p, options & FindExeOption::IgnoreExecBit);
589 if (!result.isEmpty()) {
590 return result;
591 }
592
593 // If we reach here, the executable wasn't found.
594 // So return empty string.
595 return QString();
596}
597
598// ---
599
600class Q_DECL_HIDDEN PropertySet::Private
601{
602public:
603 Private() {}
604 Private(const Private &other) {
605 copy(other);
606 }
607 void copy(const Private &other) {
608 for (AutodeletedHash<QByteArray, Property*>::ConstIterator it(other.data.constBegin());
609 it != other.data.constEnd(); ++it)
610 {
611 data.insert(it.key(), new Property(*it.value()));
612 }
613 }
614 bool operator==(const Private &other) const {
615 if (data.count() != other.data.count()) {
616 return false;
617 }
618 for (AutodeletedHash<QByteArray, Property*>::ConstIterator it(other.data.constBegin());
619 it != other.data.constEnd(); ++it)
620 {
621 AutodeletedHash<QByteArray, Property*>::ConstIterator findHere(data.constFind(it.key()));
622 if (*findHere.value() != *it.value()) {
623 return false;
624 }
625 }
626 return true;
627 }
629};
630
631PropertySet::PropertySet()
632 : d(new Private)
633{
634}
635
636PropertySet::PropertySet(const PropertySet &other)
637 : d(new Private(*other.d))
638{
639}
640
641PropertySet::~PropertySet()
642{
643 delete d;
644}
645
647{
648 if (this != &other) {
649 d->data.clear();
650 d->copy(*other.d);
651 }
652 return *this;
653}
654
655bool PropertySet::operator==(const PropertySet &other) const
656{
657 return *d == *other.d;
658}
659
660void PropertySet::insert(const QByteArray &name, const QVariant &value, const QString &caption)
661{
662 QString realCaption = caption;
663 Property *existing = d->data.value(name);
664 if (existing) {
665 existing->setValue(value);
666 if (!caption.isEmpty()) { // if not, reuse
667 existing->setCaption(caption);
668 }
669 } else {
670 if (KDb::isIdentifier(name)) {
671 d->data.insert(name, new Property(value, realCaption));
672 } else {
673 kdbWarning() << name << "cannot be used as property name";
674 }
675 }
676}
677
678void PropertySet::setCaption(const QByteArray &name, const QString &caption)
679{
680 Property *existing = d->data.value(name);
681 if (existing) {
682 existing->setCaption(caption);
683 }
684}
685
686void PropertySet::setValue(const QByteArray &name, const QVariant &value)
687{
688 Property *existing = d->data.value(name);
689 if (existing) {
690 existing->setValue(value);
691 }
692}
693
695{
696 d->data.remove(name);
697}
698
700{
701 Property *result = d->data.value(name);
702 return result ? *result : Property();
703}
704
706{
707 return d->data.keys();
708}
709
710QVariant KDbUtils::squeezedValue(const QVariant &value)
711{
712 switch(value.type()) {
713 case QVariant::String:
714 if (value.toString().length() > SQUEEZED_TEXT_LIMIT) {
715 return QVariant(value.toString().left(SQUEEZED_TEXT_LIMIT - SQUEEZED_TEXT_SUFFIX)
716 + QString::fromLatin1("...")
717 + value.toString().right(SQUEEZED_TEXT_SUFFIX)
718 + QString::fromLatin1("[%1 characters]").arg(value.toString().length()));
719 }
720 break;
722 if (value.toByteArray().length() > SQUEEZED_TEXT_LIMIT) {
723 return QVariant(value.toByteArray().left(SQUEEZED_TEXT_LIMIT - SQUEEZED_TEXT_SUFFIX)
724 + "..."
725 + value.toByteArray().right(SQUEEZED_TEXT_SUFFIX)
726 + '[' + QByteArray::number(value.toByteArray().length())
727 + " bytes]");
728 }
729 break;
730 default:
731 break;
732 }
733//! @todo add BitArray, Url, Hash, Map, Pixmap, Image?
734 return value;
735}
Autodeleting hash.
Definition KDbUtils.h:179
A set of properties.
Definition KDbUtils.h:480
void setValue(const QByteArray &name, const QVariant &value)
Sets value for property name to value.
Definition KDbUtils.cpp:686
Property property(const QByteArray &name) const
Definition KDbUtils.cpp:699
void remove(const QByteArray &name)
Removes property with a given name.
Definition KDbUtils.cpp:694
PropertySet & operator=(const PropertySet &other)
Assigns other to this property set and returns a reference to this property set.
Definition KDbUtils.cpp:646
void setCaption(const QByteArray &name, const QString &caption)
Sets caption for property name to caption.
Definition KDbUtils.cpp:678
void insert(const QByteArray &name, const QVariant &value, const QString &caption=QString())
Inserts property with a given name, value and caption.
Definition KDbUtils.cpp:660
QList< QByteArray > names() const
Definition KDbUtils.cpp:705
bool operator==(const PropertySet &other) const
Definition KDbUtils.cpp:655
A single property.
Definition KDbUtils.h:446
Property()
Constructs a null property.
Definition KDbUtils.cpp:75
A set created from static (0-terminated) array of raw null-terminated strings.
Definition KDbUtils.h:388
bool contains(const QByteArray &string) const
Definition KDbUtils.cpp:365
KDB_EXPORT bool isIdentifier(const QString &s)
KIOCORE_EXPORT StatJob * stat(const QUrl &url, JobFlags flags=DefaultFlags)
KCOREADDONS_EXPORT QString tildeExpand(const QString &path)
const QList< QKeySequence > & copy()
bool operator==(const StyleDelim &l, const StyleDelim &r)
const char * constData() const const
char * data()
QByteArray fromRawData(const char *data, qsizetype size)
QByteArray left(qsizetype len) const const
qsizetype length() const const
QByteArray number(double n, char format, int precision)
void resize(qsizetype newSize, char c)
QByteArray right(qsizetype len) const const
qsizetype size() const const
QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
bool isValid() const const
QTime time() const const
QString toString(QStringView format, QCalendar cal) const const
QString homePath()
QChar separator()
QString decodeName(const QByteArray &localFileName)
QString absoluteFilePath() const const
QString canonicalFilePath() const const
bool exists(const QString &path)
QString filePath() const const
bool isExecutable() const const
bool isFile() const const
bool makeAbsolute()
void setFile(const QDir &dir, const QString &path)
const_iterator constEnd() const const
void append(QList< T > &&value)
iterator begin()
void clear()
qsizetype count() const const
iterator end()
QObject * parent() const const
bool contains(const QSet< T > &other) const const
iterator insert(const T &value)
SectionIncludeLeadingSep
QString & append(QChar ch)
QString arg(Args &&... args) const const
QString asprintf(const char *cformat,...)
void clear()
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromLatin1(QByteArrayView str)
QString fromLocal8Bit(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QString right(qsizetype n) const const
QString section(QChar sep, qsizetype start, qsizetype end, SectionFlags flags) const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QByteArray toUtf8() const const
const QChar * unicode() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
CaseInsensitive
ISODateWithMs
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QTime fromString(QStringView string, QStringView format)
int hour() const const
bool isValid(int h, int m, int s, int ms)
int minute() const const
int msec() const const
int second() const const
QString toString(QStringView format) const const
Type type() const const
QByteArray toByteArray() const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:19:07 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.