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