Krita Source Code Documentation
Loading...
Searching...
No Matches
version_checker.h
Go to the documentation of this file.
1// This file is part of PyKrita, Krita' Python scripting plugin.
2//
3// SPDX-FileCopyrightText: 2013 Alex Turbov <i.zaufi@gmail.com>
4//
5// SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only
6
7#ifndef __VERSION_CHECKER_H__
8# define __VERSION_CHECKER_H__
9
11#include "utilities.h"
12# include <QtCore/QString>
13# include <QtCore/QStringList>
14# include <QtCore/QtGlobal>
15
16namespace PyKrita
17{
18
23{
24 enum type {
26 zero = 0
27 };
28
29public:
31 explicit version(const int _major = zero, const int _minor = zero, const int patch = zero)
34 , m_patch(patch) {
35 }
36
37 int _major() const {
38 return m_major;
39 }
40 int _minor() const {
41 return m_minor;
42 }
43 int patch() const {
44 return m_patch;
45 }
46
47 bool isValid() const {
48 return _major() != undefined && _minor() != undefined && patch() != undefined;
49 }
50
51 operator QString() const {
52 return QString("%1.%2.%3").arg(_major()).arg(_minor()).arg(patch());
53 }
54
55 static version fromString(const QString& version_str) {
56 int tmp[3] = {zero, zero, zero};
57 QStringList parts = version_str.split('.');
58 for (
59 unsigned long i = 0
60 ; i < qMin(static_cast<unsigned long>(sizeof(tmp) / sizeof(int)), static_cast<unsigned long>(parts.size()))
61 ; ++i
62 ) {
63 bool ok;
64 const int num = parts[i].toInt(&ok);
65 if (ok)
66 tmp[i] = num;
67 else {
68 tmp[i] = undefined;
69 break;
70 }
71 }
72 return version(tmp[0], tmp[1], tmp[2]);
73 };
74
75 static version fromPythonObject(PyObject* version_obj)
76 {
77 version v = tryObtainVersionFromTuple(version_obj);
78 if (!v.isValid()) {
79 // PEP396 requires __version__ to be a tuple of integers,
80 // but some modules use a string instead.
81 v = tryObtainVersionFromString(version_obj);
82 }
83 return v;
84 }
85
86 static version invalid() {
87 static version s_bad(undefined, undefined, undefined);
88 return s_bad;
89 }
90
91private:
95
96
97 static version tryObtainVersionFromTuple(PyObject* version_obj)
98 {
99 Q_ASSERT("Sanity check" && version_obj);
100
101 if (PyTuple_Check(version_obj) == 0)
102 return version::invalid();
103
104 int version_info[3] = {0, 0, 0};
105 for (unsigned i = 0; i < PyTuple_Size(version_obj); ++i) {
106 PyObject* v = PyTuple_GetItem(version_obj, i);
107 if (v && PyLong_Check(v))
108 version_info[i] = PyLong_AsLong(v);
109 else
110 version_info[i] = -1;
111 }
112 if (version_info[0] != -1 && version_info[1] != -1 && version_info[2] != -1)
113 return ::PyKrita::version(version_info[0], version_info[1], version_info[2]);
114
115 return version::invalid();
116 }
117
124 static version tryObtainVersionFromString(PyObject* version_obj)
125 {
126 Q_ASSERT("Sanity check" && version_obj);
127
128 if (!Python::isUnicode(version_obj))
129 return version::invalid();
130
131 QString version_str = Python::unicode(version_obj);
132 if (version_str.isEmpty())
133 return version::invalid();
134
135 return version::fromString(version_str);
136 }
137
138
139};
140
141inline bool operator==(const version& left, const version& right)
142{
143 return left._major() == right._major()
144 && left._minor() == right._minor()
145 && left.patch() == right.patch()
146 ;
147}
148
149inline bool operator!=(const version& left, const version& right)
150{
151 return !(left == right);
152}
153
154inline bool operator<(const version& left, const version& right)
155{
156 return left._major() < right._major()
157 || (left._major() == right._major() && left._minor() < right._minor())
158 || (left._major() == right._major() && left._minor() == right._minor() && left.patch() < right.patch())
159 ;
160}
161
162inline bool operator>(const version& left, const version& right)
163{
164 return left._major() > right._major()
165 || (left._major() == right._major() && left._minor() > right._minor())
166 || (left._major() == right._major() && left._minor() == right._minor() && left.patch() > right.patch())
167 ;
168}
169
170inline bool operator<=(const version& left, const version& right)
171{
172 return left == right || left < right;
173}
174
175inline bool operator>=(const version& left, const version& right)
176{
177 return left == right || left > right;
178}
179
180
185{
186public:
198
200 explicit version_checker(const operation op = invalid)
201 : m_op(op) {
202 }
203
204 bool isValid() const {
205 return m_op != invalid;
206 }
207
208 bool isEmpty() const {
209 return m_op == undefined;
210 }
211
212 void bind_second(const version& rhs) {
213 m_rhs = rhs;
214 }
215
216 bool operator()(const version& left) {
217 switch (m_op) {
218 case less:
219 return left < m_rhs;
220 case greater:
221 return left > m_rhs;
222 case equal:
223 return left == m_rhs;
224 case not_equal:
225 return left != m_rhs;
226 case less_or_equal:
227 return left <= m_rhs;
228 case greater_or_equal:
229 return left >= m_rhs;
230 default:
231 Q_ASSERT(!"Sanity check");
232 break;
233 }
234 return false;
235 }
236
238 return m_rhs;
239 }
240
241 QString operationToString() const {
242 QString result;
243 switch (m_op) {
244 case less:
245 result = " < ";
246 break;
247 case greater:
248 result = " > ";
249 break;
250 case equal:
251 result = " = ";
252 break;
253 case not_equal:
254 result = " != ";
255 break;
256 case less_or_equal:
257 result = " <= ";
258 break;
259 case greater_or_equal:
260 result = " >= ";
261 break;
262 default:
263 Q_ASSERT(!"Sanity check");
264 break;
265 }
266 return result;
267 }
268
269 static version_checker fromString(const QString& version_info) {
270 version_checker checker(invalid);
271 if (version_info.isEmpty())
272 return checker;
273
274 bool lookup_next_char = false;
275 int strip_lead_pos = 0;
276 switch (version_info.at(0).toLatin1()) {
277 case '<':
278 checker.m_op = less;
279 lookup_next_char = true;
280 break;
281 case '>':
282 checker.m_op = greater;
283 lookup_next_char = true;
284 break;
285 case '=':
286 strip_lead_pos = 1;
287 checker.m_op = equal;
288 break;
289 default:
290 strip_lead_pos = 0;
291 checker.m_op = equal;
292 break;
293 }
294 if (lookup_next_char) {
295 if (version_info.at(1).toLatin1() == '=') {
296 // NOTE Shift state
297 checker.m_op = operation(int(checker.m_op) + 1);
298 strip_lead_pos = 2;
299 } else {
300 strip_lead_pos = 1;
301 }
302 }
303 //
304 QString rhs_str = version_info.mid(strip_lead_pos).trimmed();
305 version rhs = version::fromString(rhs_str);
306 if (rhs.isValid())
307 checker.bind_second(rhs);
308 else
309 checker.m_op = invalid;
310 return checker;
311 }
312
313private:
316};
317
318} // namespace PyKrita
319#endif // __VERSION_CHECKER_H__
qreal v
static PyObject * unicode(const QString &string)
Convert a QString to a Python unicode object.
static bool isUnicode(PyObject *string)
Test if a Python object is compatible with a QString.
Class version_checker.
version_checker(const operation op=invalid)
Default constructor.
bool operator()(const version &left)
QString operationToString() const
static version_checker fromString(const QString &version_info)
void bind_second(const version &rhs)
Class version.
static version invalid()
bool isValid() const
static version tryObtainVersionFromTuple(PyObject *version_obj)
version(const int _major=zero, const int _minor=zero, const int patch=zero)
Default constructor.
static version fromString(const QString &version_str)
static version fromPythonObject(PyObject *version_obj)
static version tryObtainVersionFromString(PyObject *version_obj)
bool operator<(const version &left, const version &right)
bool operator==(const version &left, const version &right)
bool operator>=(const version &left, const version &right)
bool operator<=(const version &left, const version &right)
bool operator>(const version &left, const version &right)
bool operator!=(const version &left, const version &right)