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