1 /************************************************************************
2 **
3 ** @file compatibility.h
4 ** @author Roman Telezhynskyi <dismine(at)gmail.com>
5 ** @date 16 1, 2020
6 **
7 ** @brief
8 ** @copyright
9 ** This source code is part of the Valentina project, a pattern making
10 ** program, whose allow create and modeling patterns of clothing.
11 ** Copyright (C) 2020 Valentina project
12 ** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
13 **
14 ** Valentina is free software: you can redistribute it and/or modify
15 ** it under the terms of the GNU General Public License as published by
16 ** the Free Software Foundation, either version 3 of the License, or
17 ** (at your option) any later version.
18 **
19 ** Valentina is distributed in the hope that it will be useful,
20 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ** GNU General Public License for more details.
23 **
24 ** You should have received a copy of the GNU General Public License
25 ** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
26 **
27 *************************************************************************/
28 #ifndef COMPATIBILITY_H
29 #define COMPATIBILITY_H
30
31 #include <QtGlobal>
32 #include <QStringList>
33 #include <QSet>
34 #include <QVector>
35
36 class QPointF;
37
38 // Contains helpful methods to hide version dependent code. It can be deprecation of method or change in API
39
40 //---------------------------------------------------------------------------------------------------------------------
41 template <typename T, template <typename> class Cont>
ConstFirst(const Cont<T> & container)42 inline const T& ConstFirst (const Cont<T> &container)
43 {
44 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
45 return container.constFirst();
46 #else
47 return container.first(); // clazy:exclude=detaching-temporary
48 #endif
49 }
50
51 //---------------------------------------------------------------------------------------------------------------------
52 template <typename T, typename C>
ConstFirst(const C & container)53 inline const T& ConstFirst (const C &container)
54 {
55 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
56 return container.constFirst();
57 #else
58 return container.first(); // clazy:exclude=detaching-temporary
59 #endif
60 }
61
62 //---------------------------------------------------------------------------------------------------------------------
63 template <typename T, template <typename> class Cont>
ConstLast(const Cont<T> & container)64 inline const T& ConstLast (const Cont<T> &container)
65 {
66 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
67 return container.constLast();
68 #else
69 return container.last(); // clazy:exclude=detaching-temporary
70 #endif
71 }
72
73 //---------------------------------------------------------------------------------------------------------------------
74 template <typename T, typename C>
ConstLast(const C & container)75 inline const T& ConstLast (const C &container)
76 {
77 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
78 return container.constLast();
79 #else
80 return container.last(); // clazy:exclude=detaching-temporary
81 #endif
82 }
83
84 //---------------------------------------------------------------------------------------------------------------------
85 template <typename T>
Intersects(const T & l1,const T & l2,QPointF * intersectionPoint)86 inline typename T::IntersectType Intersects(const T &l1, const T &l2, QPointF *intersectionPoint)
87 {
88 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
89 return l1.intersects(l2, intersectionPoint);
90 #else
91 return l1.intersect(l2, intersectionPoint);
92 #endif
93 }
94
95 //---------------------------------------------------------------------------------------------------------------------
96 template <typename T, template <typename> class C>
ConvertToList(const C<T> & container)97 inline QList<T> ConvertToList(const C<T> &container)
98 {
99 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
100 return QList<T>(container.begin(), container.end());
101 #else
102 return container.toList();
103 #endif
104 }
105
106 //---------------------------------------------------------------------------------------------------------------------
107 template <typename T, template <typename> class C>
ConvertToSet(const C<T> & container)108 inline QSet<T> ConvertToSet(const C<T> &container)
109 {
110 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
111 return QSet<T>(container.begin(), container.end());
112 #else
113 return container.toSet();
114 #endif
115 }
116
117 //---------------------------------------------------------------------------------------------------------------------
118 template <typename T, typename C>
ConvertToSet(const C & container)119 inline QSet<T> ConvertToSet(const C &container)
120 {
121 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
122 return QSet<T>(container.begin(), container.end());
123 #else
124 return container.toSet();
125 #endif
126 }
127
128 //---------------------------------------------------------------------------------------------------------------------
129 template <typename T, template <typename> class C>
ConvertToVector(const C<T> & container)130 inline QVector<T> ConvertToVector(const C<T> &container)
131 {
132 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
133 return QVector<T>(container.begin(), container.end());
134 #else
135 return container.toVector();
136 #endif
137 }
138
139 //---------------------------------------------------------------------------------------------------------------------
140 template <typename T>
ConvertToVector(const QSet<T> & container)141 inline QVector<T> ConvertToVector(const QSet<T> &container)
142 {
143 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
144 return QVector<T>(container.begin(), container.end());
145 #else
146 return container.toList().toVector();
147 #endif
148 }
149
150 //---------------------------------------------------------------------------------------------------------------------
151 // NOTE: Delete if not necessary anymore
152 //template <typename T>
153 //inline void SwapItemsAt(T &container, int i, int j)
154 //{
155 //#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
156 // container.swapItemsAt(i, j);
157 //#else
158 // container.swap(i, j);
159 //#endif
160 //}
161
162 //---------------------------------------------------------------------------------------------------------------------
163 template <typename T>
Move(T & vector,int from,int to)164 inline void Move(T &vector, int from, int to)
165 {
166 QT_WARNING_PUSH
167 QT_WARNING_DISABLE_GCC("-Wstrict-overflow")
168
169 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
170 Q_ASSERT_X(from >= 0 && from < vector.size(), "QVector::move(int,int)", "'from' is out-of-range");
171 Q_ASSERT_X(to >= 0 && to < vector.size(), "QVector::move(int,int)", "'to' is out-of-range");
172 if (from == to) // don't detach when no-op
173 {
174 return;
175 }
176 typename T::iterator b = vector.begin();
177 from < to ? std::rotate(b + from, b + from + 1, b + to + 1):
178 std::rotate(b + to, b + from, b + from + 1);
179 #else
180 vector.move(from, to);
181 #endif // QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
182
183 QT_WARNING_POP
184 }
185
186 //---------------------------------------------------------------------------------------------------------------------
187 template <typename T>
Reverse(const QVector<T> & container)188 QVector<T> Reverse(const QVector<T> &container)
189 {
190 if (container.isEmpty())
191 {
192 return container;
193 }
194 QVector<T> reversed(container.size());
195 qint32 j = 0;
196 for (qint32 i = container.size() - 1; i >= 0; --i)
197 {
198 reversed.replace(j, container.at(i));
199 ++j;
200 }
201 return reversed;
202 }
203
204 template <typename T, template <typename> class C>
205 //---------------------------------------------------------------------------------------------------------------------
Reverse(const C<T> & container)206 C<T> Reverse(const C<T> &container)
207 {
208 return ConvertToList(Reverse(ConvertToVector(container)));
209 }
210
211 //---------------------------------------------------------------------------------------------------------------------
212 template <typename T, typename std::enable_if<std::is_same<T, QStringList>::value, T>::type* = nullptr>
Reverse(const T & container)213 T Reverse(const T &container)
214 {
215 return Reverse<QString, QList>(container);
216 }
217
218 //---------------------------------------------------------------------------------------------------------------------
219 template <typename Cont, typename Input>
AppendTo(Cont & container,const Input & input)220 inline void AppendTo(Cont &container, const Input &input)
221 {
222 #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
223 container.append(input);
224 #else
225 for (auto &item : input)
226 {
227 container.append(item);
228 }
229 #endif // QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
230 }
231
232 //---------------------------------------------------------------------------------------------------------------------
233 template <typename T>
SetIntersects(const QSet<T> & set1,const QSet<T> & set2)234 inline bool SetIntersects(const QSet<T> &set1, const QSet<T> &set2)
235 {
236 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
237 return set1.intersects(set2);
238 #else
239 const bool otherIsBigger = set2.size() > set1.size();
240 const QSet<T> &smallestSet = otherIsBigger ? set1 : set2;
241 const QSet<T> &biggestSet = otherIsBigger ? set2 : set1;
242 typename QSet<T>::const_iterator i = smallestSet.cbegin();
243 typename QSet<T>::const_iterator e = smallestSet.cend();
244 while (i != e)
245 {
246 if (biggestSet.contains(*i))
247 return true;
248 ++i;
249 }
250 return false;
251
252 #endif
253 }
254
255 #endif // COMPATIBILITY_H
256