Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qtranslator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qplatformdefs.h"
5
6#include "qtranslator.h"
7
8#ifndef QT_NO_TRANSLATION
9
10#include "qfileinfo.h"
11#include "qstring.h"
12#include "qstringlist.h"
13#include "qcoreapplication.h"
14#include "qcoreapplication_p.h"
15#include "qdatastream.h"
16#include "qendian.h"
17#include "qfile.h"
18#include "qmap.h"
19#include "qalgorithms.h"
20#include "qtranslator_p.h"
21#include "qlocale.h"
22#include "qendian.h"
23#include "qresource.h"
24
25#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
26# define QT_USE_MMAP
27# include "private/qcore_unix_p.h"
28// for mmap
29# include <sys/mman.h>
30#endif
31
32#include <stdlib.h>
33#include <new>
34
35#include "qobject_p.h"
36
37#include <vector>
38#include <memory>
39
41
44/*
45$ mcookie
463cb86418caef9c95cd211cbf60a1bddd
47$
48*/
49
50// magic number for the file
51static const int MagicLength = 16;
52static const uchar magic[MagicLength] = {
53 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
54 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
55};
56
57static inline QString dotQmLiteral() { return QStringLiteral(".qm"); }
58
59static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
60{
61 // catch the case if \a found has a zero-terminating symbol and \a len includes it.
62 // (normalize it to be without the zero-terminating symbol)
63 if (foundLen > 0 && found[foundLen-1] == '\0')
64 --foundLen;
65 return ((targetLen == foundLen) && memcmp(found, target, foundLen) == 0);
66}
67
68static void elfHash_continue(const char *name, uint &h)
69{
70 const uchar *k;
71 uint g;
72
73 k = (const uchar *) name;
74 while (*k) {
75 h = (h << 4) + *k++;
76 if ((g = (h & 0xf0000000)) != 0)
77 h ^= g >> 24;
78 h &= ~g;
79 }
80}
81
82static void elfHash_finish(uint &h)
83{
84 if (!h)
85 h = 1;
86}
87
88static uint elfHash(const char *name)
89{
90 uint hash = 0;
93 return hash;
94}
95
96/*
97 \internal
98
99 Determines whether \a rules are valid "numerus rules". Test input with this
100 function before calling numerusHelper, below.
101 */
102static bool isValidNumerusRules(const uchar *rules, uint rulesSize)
103{
104 // Disabled computation of maximum numerus return value
105 // quint32 numerus = 0;
106
107 if (rulesSize == 0)
108 return true;
109
110 quint32 offset = 0;
111 do {
112 uchar opcode = rules[offset];
113 uchar op = opcode & Q_OP_MASK;
114
115 if (opcode & 0x80)
116 return false; // Bad op
117
118 if (++offset == rulesSize)
119 return false; // Missing operand
120
121 // right operand
122 ++offset;
123
124 switch (op)
125 {
126 case Q_EQ:
127 case Q_LT:
128 case Q_LEQ:
129 break;
130
131 case Q_BETWEEN:
132 if (offset != rulesSize) {
133 // third operand
134 ++offset;
135 break;
136 }
137 return false; // Missing operand
138
139 default:
140 return false; // Bad op (0)
141 }
142
143 // ++numerus;
144 if (offset == rulesSize)
145 return true;
146
147 } while (((rules[offset] == Q_AND)
148 || (rules[offset] == Q_OR)
149 || (rules[offset] == Q_NEWRULE))
150 && ++offset != rulesSize);
151
152 // Bad op
153 return false;
154}
155
156/*
157 \internal
158
159 This function does no validation of input and assumes it is well-behaved,
160 these assumptions can be checked with isValidNumerusRules, above.
161
162 Determines which translation to use based on the value of \a n. The return
163 value is an index identifying the translation to be used.
164
165 \a rules is a character array of size \a rulesSize containing bytecode that
166 operates on the value of \a n and ultimately determines the result.
167
168 This function has O(1) space and O(rulesSize) time complexity.
169 */
170static uint numerusHelper(int n, const uchar *rules, uint rulesSize)
171{
172 uint result = 0;
173 uint i = 0;
174
175 if (rulesSize == 0)
176 return 0;
177
178 for (;;) {
179 bool orExprTruthValue = false;
180
181 for (;;) {
182 bool andExprTruthValue = true;
183
184 for (;;) {
185 bool truthValue = true;
186 int opcode = rules[i++];
187
188 int leftOperand = n;
189 if (opcode & Q_MOD_10) {
190 leftOperand %= 10;
191 } else if (opcode & Q_MOD_100) {
192 leftOperand %= 100;
193 } else if (opcode & Q_LEAD_1000) {
194 while (leftOperand >= 1000)
195 leftOperand /= 1000;
196 }
197
198 int op = opcode & Q_OP_MASK;
199 int rightOperand = rules[i++];
200
201 switch (op) {
202 case Q_EQ:
203 truthValue = (leftOperand == rightOperand);
204 break;
205 case Q_LT:
206 truthValue = (leftOperand < rightOperand);
207 break;
208 case Q_LEQ:
209 truthValue = (leftOperand <= rightOperand);
210 break;
211 case Q_BETWEEN:
212 int bottom = rightOperand;
213 int top = rules[i++];
214 truthValue = (leftOperand >= bottom && leftOperand <= top);
215 }
216
217 if (opcode & Q_NOT)
218 truthValue = !truthValue;
219
220 andExprTruthValue = andExprTruthValue && truthValue;
221
222 if (i == rulesSize || rules[i] != Q_AND)
223 break;
224 ++i;
225 }
226
227 orExprTruthValue = orExprTruthValue || andExprTruthValue;
228
229 if (i == rulesSize || rules[i] != Q_OR)
230 break;
231 ++i;
232 }
233
234 if (orExprTruthValue)
235 return result;
236
237 ++result;
238
239 if (i == rulesSize)
240 return result;
241
242 i++; // Q_NEWRULE
243 }
244
245 Q_ASSERT(false);
246 return 0;
247}
248
250{
251 Q_DECLARE_PUBLIC(QTranslator)
252public:
253 enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88, Dependencies = 0x96, Language = 0xa7 };
254
256#if defined(QT_USE_MMAP)
257 used_mmap(0),
258#endif
262
263#if defined(QT_USE_MMAP)
264 bool used_mmap : 1;
265#endif
266 char *unmapPointer; // used memory (mmap, new or resource file)
268
269 // The resource object in case we loaded the translations from a resource
270 std::unique_ptr<QResource> resource;
271
272 // used if the translator has dependencies
273 std::vector<std::unique_ptr<QTranslator>> subTranslators;
274
275 // Pointers and offsets into unmapPointer[unmapLength] array, or user
276 // provided data array
285
288
289 bool do_load(const QString &filename, const QString &directory);
290 bool do_load(const uchar *data, qsizetype len, const QString &directory);
291 QString do_translate(const char *context, const char *sourceText, const char *comment,
292 int n) const;
293 void clear();
294};
295
382{
383}
384
390{
393 Q_D(QTranslator);
394 d->clear();
395}
396
442bool QTranslator::load(const QString & filename, const QString & directory,
443 const QString & search_delimiters,
444 const QString & suffix)
445{
446 Q_D(QTranslator);
447 d->clear();
448
449 QString prefix;
450 if (QFileInfo(filename).isRelative()) {
451 prefix = directory;
452 if (prefix.size() && !prefix.endsWith(u'/'))
453 prefix += u'/';
454 }
455
456 const QString suffixOrDotQM = suffix.isNull() ? dotQmLiteral() : suffix;
457 QStringView fname(filename);
458 QString realname;
459 const QString delims = search_delimiters.isNull() ? QStringLiteral("_.") : search_delimiters;
460
461 for (;;) {
463
464 realname = prefix + fname + suffixOrDotQM;
465 fi.setFile(realname);
466 if (fi.isReadable() && fi.isFile())
467 break;
468
469 realname = prefix + fname;
470 fi.setFile(realname);
471 if (fi.isReadable() && fi.isFile())
472 break;
473
474 int rightmost = 0;
475 for (int i = 0; i < (int)delims.size(); i++) {
476 int k = fname.lastIndexOf(delims[i]);
477 if (k > rightmost)
478 rightmost = k;
479 }
480
481 // no truncations? fail
482 if (rightmost == 0)
483 return false;
484
485 fname.truncate(rightmost);
486 }
487
488 // realname is now the fully qualified name of a readable file.
489 return d->do_load(realname, directory);
490}
491
493{
494 QTranslatorPrivate *d = this;
495 bool ok = false;
496
497 if (realname.startsWith(u':')) {
498 // If the translation is in a non-compressed resource file, the data is already in
499 // memory, so no need to use QFile to copy it again.
500 Q_ASSERT(!d->resource);
501 d->resource = std::make_unique<QResource>(realname);
502 if (resource->isValid() && resource->compressionAlgorithm() == QResource::NoCompression
503 && resource->size() >= MagicLength
504 && !memcmp(resource->data(), magic, MagicLength)) {
505 d->unmapLength = resource->size();
506 d->unmapPointer = reinterpret_cast<char *>(const_cast<uchar *>(resource->data()));
507#if defined(QT_USE_MMAP)
508 d->used_mmap = false;
509#endif
510 ok = true;
511 } else {
512 resource = nullptr;
513 }
514 }
515
516 if (!ok) {
517 QFile file(realname);
519 return false;
520
521 qint64 fileSize = file.size();
522 if (fileSize < MagicLength || fileSize > std::numeric_limits<qsizetype>::max())
523 return false;
524
525 {
526 char magicBuffer[MagicLength];
527 if (MagicLength != file.read(magicBuffer, MagicLength)
528 || memcmp(magicBuffer, magic, MagicLength))
529 return false;
530 }
531
532 d->unmapLength = qsizetype(fileSize);
533
534#ifdef QT_USE_MMAP
535
536#ifndef MAP_FILE
537#define MAP_FILE 0
538#endif
539#ifndef MAP_FAILED
540#define MAP_FAILED reinterpret_cast<void *>(-1)
541#endif
542
543 int fd = file.handle();
544 if (fd >= 0) {
545 int protection = PROT_READ; // read-only memory
546 int flags = MAP_FILE | MAP_PRIVATE; // swap-backed map from file
547 void *ptr = QT_MMAP(nullptr, d->unmapLength,// any address, whole file
548 protection, flags,
549 fd, 0); // from offset 0 of fd
550 if (ptr != MAP_FAILED) {
551 file.close();
552 d->used_mmap = true;
553 d->unmapPointer = static_cast<char *>(ptr);
554 ok = true;
555 }
556 }
557#endif // QT_USE_MMAP
558
559 if (!ok) {
560 d->unmapPointer = new (std::nothrow) char[d->unmapLength];
561 if (d->unmapPointer) {
562 file.seek(0);
563 qint64 readResult = file.read(d->unmapPointer, d->unmapLength);
564 if (readResult == qint64(unmapLength))
565 ok = true;
566 }
567 }
568 }
569
570 if (ok) {
571 const QString base_dir =
573 if (d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength,
574 base_dir)) {
575 d->filePath = realname;
576 return true;
577 }
578 }
579
580#if defined(QT_USE_MMAP)
581 if (used_mmap) {
582 used_mmap = false;
583 munmap(unmapPointer, unmapLength);
584 } else
585#endif
586 if (!d->resource)
587 delete [] unmapPointer;
588
589 d->resource = nullptr;
590 d->unmapPointer = nullptr;
591 d->unmapLength = 0;
592
593 return false;
594}
595
597static bool is_readable_file(const QString &name)
598{
599 const QFileInfo fi(name);
600 return fi.isReadable() && fi.isFile();
601}
602
603static QString find_translation(const QLocale & locale,
604 const QString & filename,
605 const QString & prefix,
606 const QString & directory,
607 const QString & suffix)
608{
610 if (QFileInfo(filename).isRelative()) {
611 path = directory;
612 if (!path.isEmpty() && !path.endsWith(u'/'))
613 path += u'/';
614 }
615 const QString suffixOrDotQM = suffix.isNull() ? dotQmLiteral() : suffix;
616
617 QString realname;
618 realname += path + filename + prefix; // using += in the hope for some reserve capacity
619 const int realNameBaseSize = realname.size();
620
621 // see http://www.unicode.org/reports/tr35/#LanguageMatching for inspiration
622
623 // For each language_country returned by locale.uiLanguages(), add
624 // also a lowercase version to the list. Since these languages are
625 // used to create file names, this is important on case-sensitive
626 // file systems, where otherwise a file called something like
627 // "prefix_en_us.qm" won't be found under the "en_US" locale. Note
628 // that the Qt resource system is always case-sensitive, even on
629 // Windows (in other words: this codepath is *not* UNIX-only).
630 QStringList languages = locale.uiLanguages();
631 for (int i = languages.size()-1; i >= 0; --i) {
632 QString lang = languages.at(i);
633 QString lowerLang = lang.toLower();
634 if (lang != lowerLang)
635 languages.insert(i + 1, lowerLang);
636 }
637
638 for (QString localeName : std::as_const(languages)) {
639 localeName.replace(u'-', u'_');
640
641 // try the complete locale name first and progressively truncate from
642 // the end until a matching language tag is found (with or without suffix)
643 for (;;) {
644 realname += localeName + suffixOrDotQM;
645 if (is_readable_file(realname))
646 return realname;
647
648 realname.truncate(realNameBaseSize + localeName.size());
649 if (is_readable_file(realname))
650 return realname;
651
652 realname.truncate(realNameBaseSize);
653
654 int rightmost = localeName.lastIndexOf(u'_');
655 if (rightmost <= 0)
656 break; // no truncations anymore, break
657 localeName.truncate(rightmost);
658 }
659 }
660
661 const int realNameBaseSizeFallbacks = path.size() + filename.size();
662
663 // realname == path + filename + prefix;
664 if (!suffix.isNull()) {
665 realname.replace(realNameBaseSizeFallbacks, prefix.size(), suffix);
666 // realname == path + filename;
667 if (is_readable_file(realname))
668 return realname;
669 realname.replace(realNameBaseSizeFallbacks, suffix.size(), prefix);
670 }
671
672 // realname == path + filename + prefix;
673 if (is_readable_file(realname))
674 return realname;
675
676 realname.truncate(realNameBaseSizeFallbacks);
677 // realname == path + filename;
678 if (is_readable_file(realname))
679 return realname;
680
681 realname.truncate(0);
682 return realname;
683}
684
728bool QTranslator::load(const QLocale & locale,
729 const QString & filename,
730 const QString & prefix,
731 const QString & directory,
732 const QString & suffix)
733{
734 Q_D(QTranslator);
735 d->clear();
736 QString fname = find_translation(locale, filename, prefix, directory, suffix);
737 return !fname.isEmpty() && d->do_load(fname, directory);
738}
739
753{
754 Q_D(QTranslator);
755 d->clear();
756
757 if (!data || len < MagicLength || memcmp(data, magic, MagicLength))
758 return false;
759
760 return d->do_load(data, len, directory);
761}
762
763static quint8 read8(const uchar *data)
764{
766}
767
768static quint16 read16(const uchar *data)
769{
770 return qFromBigEndian<quint16>(data);
771}
772
773static quint32 read32(const uchar *data)
774{
775 return qFromBigEndian<quint32>(data);
776}
777
779{
780 bool ok = true;
781 const uchar *end = data + len;
782
783 data += MagicLength;
784
785 QStringList dependencies;
786 while (data < end - 5) {
787 quint8 tag = read8(data++);
788 quint32 blockLen = read32(data);
789 data += 4;
790 if (!tag || !blockLen)
791 break;
792 if (quint32(end - data) < blockLen) {
793 ok = false;
794 break;
795 }
796
798 language = QString::fromUtf8((const char *)data, blockLen);
799 } else if (tag == QTranslatorPrivate::Contexts) {
801 contextLength = blockLen;
802 } else if (tag == QTranslatorPrivate::Hashes) {
804 offsetLength = blockLen;
805 } else if (tag == QTranslatorPrivate::Messages) {
807 messageLength = blockLen;
810 numerusRulesLength = blockLen;
812 QDataStream stream(QByteArray::fromRawData((const char*)data, blockLen));
813 QString dep;
814 while (!stream.atEnd()) {
815 stream >> dep;
816 dependencies.append(dep);
817 }
818 }
819
820 data += blockLen;
821 }
822
824 ok = false;
825 if (ok) {
826 subTranslators.reserve(std::size_t(dependencies.size()));
827 for (const QString &dependency : std::as_const(dependencies)) {
828 auto translator = std::make_unique<QTranslator>();
829 ok = translator->load(dependency, directory);
830 if (!ok)
831 break;
832 subTranslators.push_back(std::move(translator));
833 }
834
835 // In case some dependencies fail to load, unload all the other ones too.
836 if (!ok)
837 subTranslators.clear();
838 }
839
840 if (!ok) {
841 messageArray = nullptr;
842 contextArray = nullptr;
843 offsetArray = nullptr;
844 numerusRulesArray = nullptr;
845 messageLength = 0;
846 contextLength = 0;
847 offsetLength = 0;
849 }
850
851 return ok;
852}
853
854static QString getMessage(const uchar *m, const uchar *end, const char *context,
855 const char *sourceText, const char *comment, uint numerus)
856{
857 const uchar *tn = nullptr;
858 uint tn_length = 0;
859 const uint sourceTextLen = uint(strlen(sourceText));
860 const uint contextLen = uint(strlen(context));
861 const uint commentLen = uint(strlen(comment));
862
863 for (;;) {
864 uchar tag = 0;
865 if (m < end)
866 tag = read8(m++);
867 switch ((Tag)tag) {
868 case Tag_End:
869 goto end;
870 case Tag_Translation: {
871 int len = read32(m);
872 if (len & 1)
873 return QString();
874 m += 4;
875 if (!numerus--) {
876 tn_length = len;
877 tn = m;
878 }
879 m += len;
880 break;
881 }
882 case Tag_Obsolete1:
883 m += 4;
884 break;
885 case Tag_SourceText: {
886 quint32 len = read32(m);
887 m += 4;
888 if (!match(m, len, sourceText, sourceTextLen))
889 return QString();
890 m += len;
891 }
892 break;
893 case Tag_Context: {
894 quint32 len = read32(m);
895 m += 4;
896 if (!match(m, len, context, contextLen))
897 return QString();
898 m += len;
899 }
900 break;
901 case Tag_Comment: {
902 quint32 len = read32(m);
903 m += 4;
904 if (*m && !match(m, len, comment, commentLen))
905 return QString();
906 m += len;
907 }
908 break;
909 default:
910 return QString();
911 }
912 }
913end:
914 if (!tn)
915 return QString();
916 QString str(tn_length / 2, Qt::Uninitialized);
917 qFromBigEndian<char16_t>(tn, str.size(), str.data());
918 return str;
919}
920
921QString QTranslatorPrivate::do_translate(const char *context, const char *sourceText,
922 const char *comment, int n) const
923{
924 if (context == nullptr)
925 context = "";
926 if (sourceText == nullptr)
927 sourceText = "";
928 if (comment == nullptr)
929 comment = "";
930
931 uint numerus = 0;
932 size_t numItems = 0;
933
934 if (!offsetLength)
935 goto searchDependencies;
936
937 /*
938 Check if the context belongs to this QTranslator. If many
939 translators are installed, this step is necessary.
940 */
941 if (contextLength) {
942 quint16 hTableSize = read16(contextArray);
943 uint g = elfHash(context) % hTableSize;
944 const uchar *c = contextArray + 2 + (g << 1);
945 quint16 off = read16(c);
946 c += 2;
947 if (off == 0)
948 return QString();
949 c = contextArray + (2 + (hTableSize << 1) + (off << 1));
950
951 const uint contextLen = uint(strlen(context));
952 for (;;) {
953 quint8 len = read8(c++);
954 if (len == 0)
955 return QString();
956 if (match(c, len, context, contextLen))
957 break;
958 c += len;
959 }
960 }
961
962 numItems = offsetLength / (2 * sizeof(quint32));
963 if (!numItems)
964 goto searchDependencies;
965
966 if (n >= 0)
968
969 for (;;) {
970 quint32 h = 0;
971 elfHash_continue(sourceText, h);
972 elfHash_continue(comment, h);
974
975 const uchar *start = offsetArray;
976 const uchar *end = start + ((numItems - 1) << 3);
977 while (start <= end) {
978 const uchar *middle = start + (((end - start) >> 4) << 3);
979 uint hash = read32(middle);
980 if (h == hash) {
981 start = middle;
982 break;
983 } else if (hash < h) {
984 start = middle + 8;
985 } else {
986 end = middle - 8;
987 }
988 }
989
990 if (start <= end) {
991 // go back on equal key
992 while (start != offsetArray && read32(start) == read32(start - 8))
993 start -= 8;
994
995 while (start < offsetArray + offsetLength) {
996 quint32 rh = read32(start);
997 start += 4;
998 if (rh != h)
999 break;
1000 quint32 ro = read32(start);
1001 start += 4;
1003 sourceText, comment, numerus);
1004 if (!tn.isNull())
1005 return tn;
1006 }
1007 }
1008 if (!comment[0])
1009 break;
1010 comment = "";
1011 }
1012
1013searchDependencies:
1014 for (const auto &translator : subTranslators) {
1015 QString tn = translator->translate(context, sourceText, comment, n);
1016 if (!tn.isNull())
1017 return tn;
1018 }
1019 return QString();
1020}
1021
1022/*
1023 Empties this translator of all contents.
1024
1025 This function works with stripped translator files.
1026*/
1027
1029{
1030 Q_Q(QTranslator);
1031 if (unmapPointer && unmapLength) {
1032#if defined(QT_USE_MMAP)
1033 if (used_mmap) {
1034 used_mmap = false;
1035 munmap(unmapPointer, unmapLength);
1036 } else
1037#endif
1038 if (!resource)
1039 delete [] unmapPointer;
1040 }
1041
1042 resource = nullptr;
1043 unmapPointer = nullptr;
1044 unmapLength = 0;
1045 messageArray = nullptr;
1046 contextArray = nullptr;
1047 offsetArray = nullptr;
1048 numerusRulesArray = nullptr;
1049 messageLength = 0;
1050 contextLength = 0;
1051 offsetLength = 0;
1053
1054 subTranslators.clear();
1055
1056 language.clear();
1057 filePath.clear();
1058
1062}
1063
1082QString QTranslator::translate(const char *context, const char *sourceText, const char *disambiguation,
1083 int n) const
1084{
1085 Q_D(const QTranslator);
1086 return d->do_translate(context, sourceText, disambiguation, n);
1087}
1088
1094{
1095 Q_D(const QTranslator);
1096 return !d->messageArray && !d->offsetArray && !d->contextArray
1097 && d->subTranslators.empty();
1098}
1099
1106{
1107 Q_D(const QTranslator);
1108 return d->language;
1109}
1110
1121{
1122 Q_D(const QTranslator);
1123 return d->filePath;
1124}
1125
1127
1128#include "moc_qtranslator.cpp"
1129
1130#endif // QT_NO_TRANSLATION
quint16 opcode
Definition bluez_data_p.h:1
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:394
static bool isTranslatorInstalled(QTranslator *translator)
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static bool removeTranslator(QTranslator *messageFile)
Removes the translation file translationFile from the list of translation files used by this applicat...
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore
Definition qcoreevent.h:45
@ LanguageChange
Definition qcoreevent.h:123
bool seek(qint64 offset) override
For random-access devices, this function sets the current position to pos, returning true on success,...
int handle() const
Returns the file handle of the file.
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
void setFile(const QString &file)
Sets the file that the QFileInfo provides information about to file.
bool isFile() const
Returns true if this object points to a file or to a symbolic link to a file.
QString absolutePath() const
Returns a file's path absolute path.
bool isReadable() const
Returns true if the user can read the file; otherwise returns false.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
qint64 size() const override
\reimp
Definition qfile.cpp:1156
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
\inmodule QtCore
Definition qobject.h:90
@ NoCompression
Definition qresource.h:23
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3794
void truncate(qsizetype pos)
Truncates the string at the given position index.
Definition qstring.cpp:6159
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:898
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5350
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString toLower() const &
Definition qstring.h:368
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
bool do_load(const QString &filename, const QString &directory)
std::unique_ptr< QResource > resource
QString do_translate(const char *context, const char *sourceText, const char *comment, int n) const
const uchar * messageArray
std::vector< std::unique_ptr< QTranslator > > subTranslators
const uchar * numerusRulesArray
const uchar * contextArray
const uchar * offsetArray
\inmodule QtCore
Definition qtranslator.h:19
QTranslator(QObject *parent=nullptr)
Constructs an empty message file object with parent parent that is not connected to any file.
~QTranslator()
Destroys the object and frees any allocated resources.
virtual bool isEmpty() const
Returns true if this translator is empty, otherwise returns false.
bool load(const QString &filename, const QString &directory=QString(), const QString &search_delimiters=QString(), const QString &suffix=QString())
Loads filename + suffix (".qm" if the suffix is not specified), which may be an absolute file name or...
QString language() const
QString filePath() const
virtual QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Returns the translation for the key (context, sourceText, disambiguation).
QHash< int, QWidget * > hash
[35multi]
QString str
[2]
Language
Definition language.h:13
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
static void * context
#define Q_NEVER_INLINE
AudioChannelLayoutTag tag
EGLStreamKHR stream
quint8 qFromBigEndian< quint8 >(const void *src)
Definition qendian.h:243
static ControlElement< T > * ptr(QWidget *widget)
const GLfloat * m
GLuint GLuint end
GLdouble GLdouble GLdouble GLdouble top
GLint GLint bottom
GLenum target
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLenum GLuint GLintptr offset
GLboolean GLboolean g
GLuint64 GLenum GLint fd
GLuint name
GLfloat n
GLfloat GLfloat GLfloat GLfloat h
const GLubyte * c
GLenum GLsizei len
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
static QT_BEGIN_NAMESPACE bool isRelative(const QString &path)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define MAP_FILE
#define MAP_FAILED
#define QStringLiteral(str)
static QString getMessage(const uchar *m, const uchar *end, const char *context, const char *sourceText, const char *comment, uint numerus)
static quint32 read32(const uchar *data)
Tag
@ Tag_End
@ Tag_Obsolete1
@ Tag_Context16
@ Tag_SourceText
@ Tag_Context
@ Tag_Obsolete2
@ Tag_Translation
@ Tag_Comment
@ Tag_SourceText16
static void elfHash_continue(const char *name, uint &h)
static bool isValidNumerusRules(const uchar *rules, uint rulesSize)
static Q_NEVER_INLINE bool is_readable_file(const QString &name)
static const int MagicLength
static QString dotQmLiteral()
static uint elfHash(const char *name)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
static const uchar magic[MagicLength]
static uint numerusHelper(int n, const uchar *rules, uint rulesSize)
static QString find_translation(const QLocale &locale, const QString &filename, const QString &prefix, const QString &directory, const QString &suffix)
static quint8 read8(const uchar *data)
static quint16 read16(const uchar *data)
static void elfHash_finish(uint &h)
@ Q_NOT
@ Q_MOD_10
@ Q_AND
@ Q_LT
@ Q_NEWRULE
@ Q_MOD_100
@ Q_OP_MASK
@ Q_EQ
@ Q_OR
@ Q_BETWEEN
@ Q_LEQ
@ Q_LEAD_1000
unsigned int quint32
Definition qtypes.h:45
unsigned char uchar
Definition qtypes.h:27
unsigned short quint16
Definition qtypes.h:43
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
unsigned char quint8
Definition qtypes.h:41
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFile file
[0]
QFileInfo fi("c:/temp/foo")
[newstuff]
QObject::connect nullptr
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent