1 #ifndef QUAZIP_QT_COMPAT_H
2 #define QUAZIP_QT_COMPAT_H
3 
4 /*
5  * For some reason, Qt 5.14 and 5.15 introduced a whole mess of seemingly random
6  * moves and deprecations. To avoid populating code with #ifs,
7  * we handle this stuff here, as well as some other compatibility issues.
8  *
9  * Some includes are repeated just in case we want to split this file later.
10  */
11 
12 #include <QtCore/Qt>
13 #include <QtCore/QtGlobal>
14 
15 // Legacy encodings are still everywhere, but the Qt team decided we
16 // don't need them anymore and moved them out of Core in Qt 6.
17 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
18 #  include <QtCore5Compat/QTextCodec>
19 #else
20 #  include <QtCore/QTextCodec>
21 #endif
22 
23 // QSaveFile terribly breaks the is-a idiom (Liskov substitution principle):
24 // QSaveFile is-a QIODevice, but it makes close() private and aborts
25 // if you call it through the base class. Hence this ugly hack:
26 #if (QT_VERSION >= 0x050100)
27 #include <QtCore/QSaveFile>
quazip_close(QIODevice * device)28 inline bool quazip_close(QIODevice *device) {
29     QSaveFile *file = qobject_cast<QSaveFile*>(device);
30     if (file != nullptr) {
31         // We have to call the ugly commit() instead:
32         return file->commit();
33     } else {
34         device->close();
35         return true;
36     }
37 }
38 #else
quazip_close(QIODevice * device)39 inline bool quazip_close(QIODevice *device) {
40     device->close();
41     return true;
42 }
43 #endif
44 
45 // this is yet another stupid move and deprecation
46 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
47 using Qt::SkipEmptyParts;
48 #else
49 #include <QtCore/QString>
50 const auto SkipEmptyParts = QString::SplitBehavior::SkipEmptyParts;
51 #endif
52 
53 // and yet another... (why didn't they just make qSort delegate to std::sort?)
54 #include <QtCore/QList>
55 #if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
56 #include <algorithm>
57 template<typename T, typename C>
quazip_sort(T begin,T end,C comparator)58 inline void quazip_sort(T begin, T end, C comparator) {
59     std::sort(begin, end, comparator);
60 }
61 #else
62 #include <QtCore/QtAlgorithms>
63 template<typename T, typename C>
quazip_sort(T begin,T end,C comparator)64 inline void quazip_sort(T begin, T end, C comparator) {
65     qSort(begin, end, comparator);
66 }
67 #endif
68 
69 // this is a stupid rename...
70 #include <QtCore/QDateTime>
71 #include <QtCore/QFileInfo>
72 #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
quazip_ctime(const QFileInfo & fi)73 inline QDateTime quazip_ctime(const QFileInfo &fi) {
74     return fi.birthTime();
75 }
76 #else
quazip_ctime(const QFileInfo & fi)77 inline QDateTime quazip_ctime(const QFileInfo &fi) {
78     return fi.created();
79 }
80 #endif
81 
82 // this is just a slightly better alternative
83 #include <QtCore/QFileInfo>
84 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
quazip_is_symlink(const QFileInfo & fi)85 inline bool quazip_is_symlink(const QFileInfo &fi) {
86     return fi.isSymbolicLink();
87 }
88 #else
quazip_is_symlink(const QFileInfo & fi)89 inline bool quazip_is_symlink(const QFileInfo &fi) {
90     // also detects *.lnk on Windows, but better than nothing
91     return fi.isSymLink();
92 }
93 #endif
94 
95 // I'm not even sure what this one is, but nevertheless
96 #include <QtCore/QFileInfo>
97 #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
quazip_symlink_target(const QFileInfo & fi)98 inline QString quazip_symlink_target(const QFileInfo &fi) {
99     return fi.symLinkTarget();
100 }
101 #else
quazip_symlink_target(const QFileInfo & fi)102 inline QString quazip_symlink_target(const QFileInfo &fi) {
103     return fi.readLink(); // What's the difference? I've no idea.
104 }
105 #endif
106 
107 // this is not a deprecation but an improvement, for a change
108 #include <QtCore/QDateTime>
109 #if (QT_VERSION >= 0x040700)
quazip_ntfs_ticks(const QDateTime & time,int fineTicks)110 inline quint64 quazip_ntfs_ticks(const QDateTime &time, int fineTicks) {
111     QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC);
112     return base.msecsTo(time) * 10000 + fineTicks;
113 }
114 #else
quazip_ntfs_ticks(const QDateTime & time,int fineTicks)115 inline quint64 quazip_ntfs_ticks(const QDateTime &time, int fineTicks) {
116     QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC);
117     QDateTime utc = time.toUTC();
118     return (static_cast<qint64>(base.date().daysTo(utc.date()))
119             * Q_INT64_C(86400000)
120             + static_cast<qint64>(base.time().msecsTo(utc.time())))
121         * Q_INT64_C(10000) + fineTicks;
122 }
123 #endif
124 
125 // yet another improvement...
126 #include <QtCore/QDateTime>
127 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) // Yay! Finally a way to get time as qint64!
quazip_to_time64_t(const QDateTime & time)128 inline qint64 quazip_to_time64_t(const QDateTime &time) {
129     return time.toSecsSinceEpoch();
130 }
131 #else
quazip_to_time64_t(const QDateTime & time)132 inline qint64 quazip_to_time64_t(const QDateTime &time) {
133     return static_cast<qint64>(time.toTime_t()); // 32 bits only, but better than nothing
134 }
135 #endif
136 
137 #include <QtCore/QTextStream>
138 // and another stupid move
139 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
140 const auto quazip_endl = Qt::endl;
141 #else
142 const auto quazip_endl = endl;
143 #endif
144 
145 #endif // QUAZIP_QT_COMPAT_H
146