diff --git a/static/reports/clang/master/index.html b/static/reports/clang/master/index.html index 76f5d7b05..f8280ddce 100644 --- a/static/reports/clang/master/index.html +++ b/static/reports/clang/master/index.html @@ -1,328 +1,325 @@
-User: | gilles@localhost |
---|---|
Working Directory: | /mnt/devel/GIT/6.x/build.scan |
Command Line: | make -j7 |
Clang Version: | clang version 8.0.0 (Mageia 8.0.0-1.mga7) |
Date: | Sat Nov 23 06:10:05 2019 |
Date: | Sat Nov 23 12:06:37 2019 |
Bug Type | Quantity | Display? |
All Bugs | 7 | |
All Bugs | 6 | |
API | ||
---|---|---|
Argument with 'nonnull' attribute passed null | 1 | |
Dead store | ||
Dead assignment | 1 | |
Dead increment | 1 | |
Dead initialization | 1 | |
Logic error | ||
Assigned value is garbage or undefined | 1 | |
Branch condition evaluates to a garbage value | 1 | |
Called C++ object pointer is null | 1 | |
Dereference of null pointer | 1 | |
Division by zero | 1 | |
Result of operation is garbage or undefined | 1 | |
Returning null reference | 1 | |
Stack address stored into global variable | 1 | |
Uninitialized argument value | 1 | |
Memory error | ||
Bad deallocator | 1 | |
Memory leak | 4 | |
Memory leak | 3 | |
Use of zero allocated | 1 | |
Use-after-free | 2 |
Bug Group | Bug Type ▾ | File | Function/Method | Line | Path Length | |
Memory error | Bad deallocator | usr/lib64/qt5/include/QtCore/qscopedpointer.h | cleanup | 60 | 5 | View Report | - +
Memory error | Bad deallocator | usr/lib64/qt5/include/QtCore/qscopedpointer.h | cleanup | 60 | 5 | View Report | +
Memory error | Memory leak | mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp | readSettings | 191 | 4 | View Report | -
Memory error | Memory leak | mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp | loginHandle | 89 | 6 | View Report | - +
Memory error | Memory leak | mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp | slotAddBlackFrame | 237 | 4 | View Report | +
Memory error | Memory leak | mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp | readSettings | 191 | 4 | View Report | +
Memory error | Memory leak | mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp | slotAddBlackFrame | 237 | 4 | View Report | -
Memory error | Memory leak | usr/lib64/qt5/include/QtTest/qtestcase.h | qCompare | 359 | 9 | View Report | - +
Memory error | Memory leak | usr/lib64/qt5/include/QtTest/qtestcase.h | qCompare | 359 | 9 | View Report | +
Memory error | Use-after-free | usr/lib64/qt5/include/QtCore/qshareddata.h | constData | 161 | 9 | View Report | -
Memory error | Use-after-free | usr/lib64/qt5/include/QtCore/qshareddata.h | constData | 83 | 29 | View Report | +
Memory error | Use-after-free | usr/lib64/qt5/include/QtCore/qshareddata.h | constData | 83 | 29 | View Report | - -
Memory error | Use-after-free | usr/lib64/qt5/include/QtCore/qshareddata.h | operator-> | 159 | 10 | View Report | +
File: | usr/lib64/qt5/include/QtCore/qshareddata.h |
Warning: | line 83, column 41 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
-Keyboard shortcuts:
1 | /* ============================================================ | |||
2 | * | |||
3 | * This file is a part of digiKam project | |||
4 | * https://www.digikam.org | |||
5 | * | |||
6 | * Date : 2009-07-05 | |||
7 | * Description : Access to the properties of an Item / Tag pair, i.e., a tag associated to an item | |||
8 | * | |||
9 | * Copyright (C) 2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> | |||
10 | * | |||
11 | * This program is free software; you can redistribute it | |||
12 | * and/or modify it under the terms of the GNU General | |||
13 | * Public License as published by the Free Software Foundation; | |||
14 | * either version 2, or (at your option) | |||
15 | * any later version. | |||
16 | * | |||
17 | * This program is distributed in the hope that it will be useful, | |||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
20 | * GNU General Public License for more details. | |||
21 | * | |||
22 | * ============================================================ */ | |||
23 | ||||
24 | #include "itemtagpair.h" | |||
25 | ||||
26 | // Qt includes | |||
27 | ||||
28 | #include <QSharedData> | |||
29 | ||||
30 | // Local includes | |||
31 | ||||
32 | #include "digikam_debug.h" | |||
33 | #include "coredb.h" | |||
34 | #include "coredbaccess.h" | |||
35 | #include "iteminfo.h" | |||
36 | #include "tagscache.h" | |||
37 | ||||
38 | namespace Digikam | |||
39 | { | |||
40 | ||||
41 | typedef QSharedDataPointer<ItemTagPairPriv> ItemTagPairPrivSharedPointer; | |||
42 | ||||
43 | // NOTE: do not use Q_DECL_HIDDEN hidden here to prevent export symbols warnings under Windows. | |||
44 | class ItemTagPairPriv : public QSharedData | |||
45 | { | |||
46 | ||||
47 | public: | |||
48 | ||||
49 | static ItemTagPairPrivSharedPointer createGuarded(qlonglong imageId, int tagId); | |||
50 | ||||
51 | ItemTagPairPriv() | |||
52 | { | |||
53 | tagId = -1; | |||
54 | isAssigned = false; | |||
55 | propertiesLoaded = false; | |||
56 | } | |||
57 | ||||
58 | bool isNull() const; | |||
59 | void init(const ItemInfo& info, int tagId); | |||
60 | void checkProperties(); | |||
61 | ||||
62 | public: | |||
63 | ||||
64 | ItemInfo info; | |||
65 | int tagId; | |||
66 | bool isAssigned; | |||
67 | bool propertiesLoaded; | |||
68 | QMultiMap<QString, QString> properties; | |||
69 | }; | |||
70 | ||||
71 | // ----------------------------------------------------------------------- | |||
72 | ||||
73 | class Q_DECL_HIDDEN__attribute__((visibility("hidden"))) ItemTagPairPrivSharedNull : public ItemTagPairPrivSharedPointer | |||
74 | { | |||
75 | public: | |||
76 | ||||
77 | ItemTagPairPrivSharedNull() | |||
78 | : QSharedDataPointer<ItemTagPairPriv>(new ItemTagPairPriv) | |||
79 | { | |||
80 | } | |||
81 | }; | |||
82 | ||||
83 | Q_GLOBAL_STATIC(ItemTagPairPrivSharedNull, imageTagPairPrivSharedNull)namespace { namespace Q_QGS_imageTagPairPrivSharedNull { typedef ItemTagPairPrivSharedNull Type; QBasicAtomicInt guard = { QtGlobalStatic ::Uninitialized }; __attribute__((visibility("hidden"))) inline Type *innerFunction() { struct HolderBase { ~HolderBase() noexcept { if (guard.load() == QtGlobalStatic::Initialized) guard.store (QtGlobalStatic::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept(noexcept(Type ()) ) : value () { guard.store(QtGlobalStatic::Initialized); } } holder ; return &holder.value; } } } static QGlobalStatic<ItemTagPairPrivSharedNull , Q_QGS_imageTagPairPrivSharedNull::innerFunction, Q_QGS_imageTagPairPrivSharedNull ::guard> imageTagPairPrivSharedNull; | |||
84 | ||||
85 | // ----------------------------------------------------------------------- | |||
86 | ||||
87 | ItemTagPairPrivSharedPointer ItemTagPairPriv::createGuarded(qlonglong imageId, int tagId) | |||
88 | { | |||
89 | if (imageId <= 0 || tagId <= 0) | |||
90 | { | |||
91 | qCDebug(DIGIKAM_DATABASE_LOG)for (bool qt_category_enabled = DIGIKAM_DATABASE_LOG().isDebugEnabled (); qt_category_enabled; qt_category_enabled = false) QMessageLogger ("/mnt/devel/GIT/6.x/core/libs/database/item/containers/itemtagpair.cpp" , 91, __PRETTY_FUNCTION__, DIGIKAM_DATABASE_LOG().categoryName ()).debug() << "Attempt to create invalid tag pair image id" << imageId << "tag id" << tagId; | |||
92 | return *imageTagPairPrivSharedNull; | |||
93 | } | |||
94 | ||||
95 | return ItemTagPairPrivSharedPointer(new ItemTagPairPriv); | |||
96 | } | |||
97 | ||||
98 | void ItemTagPairPriv::init(const ItemInfo& i, int t) | |||
99 | { | |||
100 | if (isNull()) | |||
101 | { | |||
102 | return; | |||
103 | } | |||
104 | ||||
105 | tagId = t; | |||
106 | info = i; | |||
107 | isAssigned = info.tagIds().contains(tagId); | |||
108 | } | |||
109 | ||||
110 | void ItemTagPairPriv::checkProperties() | |||
111 | { | |||
112 | if (!isNull() && !propertiesLoaded) | |||
113 | { | |||
114 | QList<ImageTagProperty> props = CoreDbAccess().db()->getImageTagProperties(info.id(), tagId); | |||
115 | ||||
116 | foreach (const ImageTagProperty& p, props)for (auto _container_ = QtPrivate::qMakeForeachContainer(props ); _container_.control && _container_.i != _container_ .e; ++_container_.i, _container_.control ^= 1) for (const ImageTagProperty & p = *_container_.i; _container_.control; _container_.control = 0) | |||
117 | { | |||
118 | properties.insert(p.property, p.value); | |||
119 | } | |||
120 | ||||
121 | propertiesLoaded = true; | |||
122 | } | |||
123 | } | |||
124 | ||||
125 | bool ItemTagPairPriv::isNull() const | |||
126 | { | |||
127 | return this == imageTagPairPrivSharedNull->constData(); | |||
128 | } | |||
129 | ||||
130 | ItemTagPair::ItemTagPair() | |||
131 | : d(*imageTagPairPrivSharedNull) | |||
132 | { | |||
133 | } | |||
134 | ||||
135 | ItemTagPair::ItemTagPair(qlonglong imageId, int tagId) | |||
136 | : d(ItemTagPairPriv::createGuarded(imageId, tagId)) | |||
| ||||
137 | { | |||
138 | d->init(ItemInfo(imageId), tagId); | |||
139 | } | |||
140 | ||||
141 | ItemTagPair::ItemTagPair(const ItemInfo& info, int tagId) | |||
142 | : d(ItemTagPairPriv::createGuarded(info.id(), tagId)) | |||
143 | { | |||
144 | d->init(info, tagId); | |||
145 | } | |||
146 | ||||
147 | ItemTagPair::~ItemTagPair() | |||
148 | { | |||
149 | } | |||
150 | ||||
151 | ItemTagPair::ItemTagPair(const ItemTagPair& other) | |||
152 | { | |||
153 | d = other.d; | |||
154 | } | |||
155 | ||||
156 | ItemTagPair& ItemTagPair::operator=(const ItemTagPair& other) | |||
157 | { | |||
158 | d = other.d; | |||
159 | return *this; | |||
160 | } | |||
161 | ||||
162 | bool ItemTagPair::isNull() const | |||
163 | { | |||
164 | return d == *imageTagPairPrivSharedNull; | |||
165 | } | |||
166 | ||||
167 | QList<ItemTagPair> ItemTagPair::availablePairs(qlonglong imageId) | |||
168 | { | |||
169 | return availablePairs(ItemInfo(imageId)); | |||
170 | } | |||
171 | ||||
172 | QList<ItemTagPair> ItemTagPair::availablePairs(const ItemInfo& info) | |||
173 | { | |||
174 | QList<ItemTagPair> pairs; | |||
175 | ||||
176 | if (info.isNull()) | |||
177 | { | |||
178 | return pairs; | |||
179 | } | |||
180 | ||||
181 | QList<int> tagIds = CoreDbAccess().db()->getTagIdsWithProperties(info.id()); | |||
182 | ||||
183 | foreach (int tagId, tagIds)for (auto _container_ = QtPrivate::qMakeForeachContainer(tagIds ); _container_.control && _container_.i != _container_ .e; ++_container_.i, _container_.control ^= 1) for (int tagId = *_container_.i; _container_.control; _container_.control = 0) | |||
184 | { | |||
185 | pairs << ItemTagPair(info, tagId); | |||
186 | } | |||
187 | ||||
188 | return pairs; | |||
189 | } | |||
190 | ||||
191 | qlonglong ItemTagPair::imageId() const | |||
192 | { | |||
193 | return d->info.id(); | |||
194 | } | |||
195 | ||||
196 | int ItemTagPair::tagId() const | |||
197 | { | |||
198 | return d->tagId; | |||
199 | } | |||
200 | ||||
201 | bool ItemTagPair::isAssigned() const | |||
202 | { | |||
203 | return d->isAssigned; | |||
204 | } | |||
205 | ||||
206 | void ItemTagPair::assignTag() | |||
207 | { | |||
208 | if (!d->isNull() && !d->isAssigned) | |||
209 | { | |||
210 | d->info.setTag(d->tagId); | |||
211 | d->isAssigned = true; | |||
212 | } | |||
213 | } | |||
214 | ||||
215 | void ItemTagPair::unAssignTag() | |||
216 | { | |||
217 | if (!d->isNull() && d->isAssigned) | |||
218 | { | |||
219 | d->info.removeTag(d->tagId); | |||
220 | d->isAssigned = false; | |||
221 | } | |||
222 | } | |||
223 | ||||
224 | bool ItemTagPair::hasProperty(const QString& key) const | |||
225 | { | |||
226 | d->checkProperties(); | |||
227 | return d->properties.contains(key); | |||
228 | } | |||
229 | ||||
230 | bool ItemTagPair::hasAnyProperty(const QStringList& keys) const | |||
231 | { | |||
232 | d->checkProperties(); | |||
233 | ||||
234 | foreach (const QString& key, keys)for (auto _container_ = QtPrivate::qMakeForeachContainer(keys ); _container_.control && _container_.i != _container_ .e; ++_container_.i, _container_.control ^= 1) for (const QString & key = *_container_.i; _container_.control; _container_. control = 0) | |||
235 | { | |||
236 | if (d->properties.contains(key)) | |||
237 | { | |||
238 | return true; | |||
239 | } | |||
240 | } | |||
241 | ||||
242 | return false; | |||
243 | } | |||
244 | ||||
245 | bool ItemTagPair::hasValue(const QString& key, const QString& value) const | |||
246 | { | |||
247 | d->checkProperties(); | |||
248 | return d->properties.contains(key, value); | |||
249 | } | |||
250 | ||||
251 | QString ItemTagPair::value(const QString& key) const | |||
252 | { | |||
253 | d->checkProperties(); | |||
254 | return d->properties.value(key); | |||
255 | } | |||
256 | ||||
257 | QStringList ItemTagPair::allValues(const QStringList& keys) const | |||
258 | { | |||
259 | d->checkProperties(); | |||
260 | QStringList values; | |||
261 | ||||
262 | foreach (const QString& key, keys)for (auto _container_ = QtPrivate::qMakeForeachContainer(keys ); _container_.control && _container_.i != _container_ .e; ++_container_.i, _container_.control ^= 1) for (const QString & key = *_container_.i; _container_.control; _container_. control = 0) | |||
263 | { | |||
264 | values << d->properties.values(key); | |||
265 | } | |||
266 | ||||
267 | return values; | |||
268 | } | |||
269 | ||||
270 | QStringList ItemTagPair::values(const QString& key) const | |||
271 | { | |||
272 | d->checkProperties(); | |||
273 | return d->properties.values(key); | |||
274 | } | |||
275 | ||||
276 | ||||
277 | QStringList ItemTagPair::propertyKeys() const | |||
278 | { | |||
279 | d->checkProperties(); | |||
280 | return d->properties.keys(); | |||
281 | } | |||
282 | ||||
283 | QMap<QString, QString> ItemTagPair::properties() const | |||
284 | { | |||
285 | d->checkProperties(); | |||
286 | return d->properties; | |||
287 | } | |||
288 | ||||
289 | void ItemTagPair::setProperty(const QString& key, const QString& value) | |||
290 | { | |||
291 | if (d->isNull() || d->info.isNull()) | |||
292 | { | |||
293 | return; | |||
294 | } | |||
295 | ||||
296 | d->checkProperties(); | |||
297 | ||||
298 | // for single entries in db, this can of course be optimized using a single UPDATE WHERE | |||
299 | removeProperties(key); | |||
300 | d->properties.replace(key, value); | |||
301 | CoreDbAccess().db()->addImageTagProperty(d->info.id(), d->tagId, key, value); | |||
302 | } | |||
303 | ||||
304 | void ItemTagPair::addProperty(const QString& key, const QString& value) | |||
305 | { | |||
306 | if (d->isNull() || d->info.isNull()) | |||
307 | { | |||
308 | return; | |||
309 | } | |||
310 | ||||
311 | d->checkProperties(); | |||
312 | ||||
313 | if (!d->properties.contains(key, value)) | |||
314 | { | |||
315 | d->properties.insert(key, value); | |||
316 | CoreDbAccess().db()->addImageTagProperty(d->info.id(), d->tagId, key, value); | |||
317 | } | |||
318 | } | |||
319 | ||||
320 | void ItemTagPair::removeProperty(const QString& key, const QString& value) | |||
321 | { | |||
322 | if (d->isNull() || d->info.isNull()) | |||
323 | { | |||
324 | return; | |||
325 | } | |||
326 | ||||
327 | d->checkProperties(); | |||
328 | ||||
329 | if (d->properties.contains(key, value)) | |||
330 | { | |||
331 | CoreDbAccess().db()->removeImageTagProperties(d->info.id(), d->tagId, key, value); | |||
332 | d->properties.remove(key, value); | |||
333 | } | |||
334 | } | |||
335 | ||||
336 | void ItemTagPair::removeProperties(const QString& key) | |||
337 | { | |||
338 | if (d->isNull() || d->info.isNull()) | |||
339 | { | |||
340 | return; | |||
341 | } | |||
342 | ||||
343 | d->checkProperties(); | |||
344 | ||||
345 | if (d->properties.contains(key)) | |||
346 | { | |||
347 | CoreDbAccess().db()->removeImageTagProperties(d->info.id(), d->tagId, key); | |||
348 | d->properties.remove(key); | |||
349 | } | |||
350 | } | |||
351 | ||||
352 | void ItemTagPair::clearProperties() | |||
353 | { | |||
354 | if (d->isNull() || d->info.isNull()) | |||
355 | { | |||
356 | return; | |||
357 | } | |||
358 | ||||
359 | if (d->propertiesLoaded && d->properties.isEmpty()) | |||
360 | { | |||
361 | return; | |||
362 | } | |||
363 | ||||
364 | CoreDbAccess().db()->removeImageTagProperties(d->info.id(), d->tagId); | |||
365 | d->properties.clear(); | |||
366 | d->propertiesLoaded = true; | |||
367 | } | |||
368 | ||||
369 | } // namespace Digikam |
1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 Intel Corporation. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtCore module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include <QtCore/qglobal.h> |
41 | |
42 | #ifndef QGLOBALSTATIC_H |
43 | #define QGLOBALSTATIC_H |
44 | |
45 | #include <QtCore/qatomic.h> |
46 | |
47 | QT_BEGIN_NAMESPACE |
48 | |
49 | namespace QtGlobalStatic { |
50 | enum GuardValues { |
51 | Destroyed = -2, |
52 | Initialized = -1, |
53 | Uninitialized = 0, |
54 | Initializing = 1 |
55 | }; |
56 | } |
57 | |
58 | #if !QT_CONFIG(thread)(1/1 == 1) || defined(Q_COMPILER_THREADSAFE_STATICS) |
59 | // some compilers support thread-safe statics |
60 | // The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4 |
61 | // support it. C++11 also requires this behavior. |
62 | // Clang and Intel CC masquerade as GCC when compiling on Linux. |
63 | // |
64 | // Apple's libc++abi however uses a global lock for initializing local statics, |
65 | // which will block other threads also trying to initialize a local static |
66 | // until the constructor returns ... |
67 | // We better avoid these kind of problems by using our own locked implementation. |
68 | |
69 | #if defined(Q_OS_UNIX) && defined(Q_CC_INTEL) |
70 | // Work around Intel issue ID 6000058488: |
71 | // local statics inside an inline function inside an anonymous namespace are global |
72 | // symbols (this affects the IA-64 C++ ABI, so OS X and Linux only) |
73 | # define Q_GLOBAL_STATIC_INTERNAL_DECORATION__attribute__((visibility("hidden"))) inline Q_DECL_HIDDEN__attribute__((visibility("hidden"))) |
74 | #else |
75 | # define Q_GLOBAL_STATIC_INTERNAL_DECORATION__attribute__((visibility("hidden"))) inline Q_DECL_HIDDEN__attribute__((visibility("hidden"))) inline |
76 | #endif |
77 | |
78 | #define Q_GLOBAL_STATIC_INTERNAL(ARGS)__attribute__((visibility("hidden"))) inline Type *innerFunction () { struct HolderBase { ~HolderBase() noexcept { if (guard.load () == QtGlobalStatic::Initialized) guard.store(QtGlobalStatic ::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept(noexcept(Type ARGS)) : value ARGS { guard.store(QtGlobalStatic::Initialized); } } holder; return &holder.value; } \ |
79 | Q_GLOBAL_STATIC_INTERNAL_DECORATION__attribute__((visibility("hidden"))) inline Type *innerFunction() \ |
80 | { \ |
81 | struct HolderBase { \ |
82 | ~HolderBase() Q_DECL_NOTHROWnoexcept \ |
83 | { if (guard.load() == QtGlobalStatic::Initialized) \ |
84 | guard.store(QtGlobalStatic::Destroyed); } \ |
85 | }; \ |
86 | static struct Holder : public HolderBase { \ |
87 | Type value; \ |
88 | Holder() \ |
89 | Q_DECL_NOEXCEPT_EXPR(noexcept(Type ARGS))noexcept(noexcept(Type ARGS)) \ |
90 | : value ARGS \ |
91 | { guard.store(QtGlobalStatic::Initialized); } \ |
92 | } holder; \ |
93 | return &holder.value; \ |
94 | } |
95 | #else |
96 | // We don't know if this compiler supports thread-safe global statics |
97 | // so use our own locked implementation |
98 | |
99 | QT_END_NAMESPACE |
100 | #include <QtCore/qmutex.h> |
101 | QT_BEGIN_NAMESPACE |
102 | |
103 | #define Q_GLOBAL_STATIC_INTERNAL(ARGS)__attribute__((visibility("hidden"))) inline Type *innerFunction () { struct HolderBase { ~HolderBase() noexcept { if (guard.load () == QtGlobalStatic::Initialized) guard.store(QtGlobalStatic ::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept(noexcept(Type ARGS)) : value ARGS { guard.store(QtGlobalStatic::Initialized); } } holder; return &holder.value; } \ |
104 | Q_DECL_HIDDEN__attribute__((visibility("hidden"))) inline Type *innerFunction() \ |
105 | { \ |
106 | static Type *d; \ |
107 | static QBasicMutex mutex; \ |
108 | int x = guard.loadAcquire(); \ |
109 | if (Q_UNLIKELY(x >= QtGlobalStatic::Uninitialized)__builtin_expect(!!(x >= QtGlobalStatic::Uninitialized), false )) { \ |
110 | QMutexLocker locker(&mutex); \ |
111 | if (guard.load() == QtGlobalStatic::Uninitialized) { \ |
112 | d = new Type ARGS; \ |
113 | static struct Cleanup { \ |
114 | ~Cleanup() { \ |
115 | delete d; \ |
116 | guard.store(QtGlobalStatic::Destroyed); \ |
117 | } \ |
118 | } cleanup; \ |
119 | guard.storeRelease(QtGlobalStatic::Initialized); \ |
120 | } \ |
121 | } \ |
122 | return d; \ |
123 | } |
124 | #endif |
125 | |
126 | // this class must be POD, unless the compiler supports thread-safe statics |
127 | template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> |
128 | struct QGlobalStatic |
129 | { |
130 | typedef T Type; |
131 | |
132 | bool isDestroyed() const { return guard.load() <= QtGlobalStatic::Destroyed; } |
133 | bool exists() const { return guard.load() == QtGlobalStatic::Initialized; } |
134 | operator Type *() { if (isDestroyed()) return 0; return innerFunction(); } |
135 | Type *operator()() { if (isDestroyed()) return 0; return innerFunction(); } |
136 | Type *operator->() |
137 | { |
138 | Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed")((!isDestroyed()) ? static_cast<void>(0) : qt_assert_x( "Q_GLOBAL_STATIC", "The global static was used after being destroyed" , "/usr/lib64/qt5/include/QtCore/qglobalstatic.h", 138)); |
139 | return innerFunction(); |
140 | } |
141 | Type &operator*() |
142 | { |
143 | Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed")((!isDestroyed()) ? static_cast<void>(0) : qt_assert_x( "Q_GLOBAL_STATIC", "The global static was used after being destroyed" , "/usr/lib64/qt5/include/QtCore/qglobalstatic.h", 143)); |
144 | return *innerFunction(); |
145 | } |
146 | }; |
147 | |
148 | #define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)namespace { namespace Q_QGS_NAME { typedef TYPE Type; QBasicAtomicInt guard = { QtGlobalStatic::Uninitialized }; __attribute__((visibility ("hidden"))) inline Type *innerFunction() { struct HolderBase { ~HolderBase() noexcept { if (guard.load() == QtGlobalStatic ::Initialized) guard.store(QtGlobalStatic::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept (noexcept(Type ARGS)) : value ARGS { guard.store(QtGlobalStatic ::Initialized); } } holder; return &holder.value; } } } static QGlobalStatic<TYPE, Q_QGS_NAME::innerFunction, Q_QGS_NAME ::guard> NAME; \ |
149 | namespace { namespace Q_QGS_ ## NAME { \ |
150 | typedef TYPE Type; \ |
151 | QBasicAtomicInt guard = Q_BASIC_ATOMIC_INITIALIZER(QtGlobalStatic::Uninitialized){ QtGlobalStatic::Uninitialized }; \ |
152 | Q_GLOBAL_STATIC_INTERNAL(ARGS)__attribute__((visibility("hidden"))) inline Type *innerFunction () { struct HolderBase { ~HolderBase() noexcept { if (guard.load () == QtGlobalStatic::Initialized) guard.store(QtGlobalStatic ::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept(noexcept(Type ARGS)) : value ARGS { guard.store(QtGlobalStatic::Initialized); } } holder; return &holder.value; } \ |
153 | } } \ |
154 | static QGlobalStatic<TYPE, \ |
155 | Q_QGS_ ## NAME::innerFunction, \ |
156 | Q_QGS_ ## NAME::guard> NAME; |
157 | |
158 | #define Q_GLOBAL_STATIC(TYPE, NAME)namespace { namespace Q_QGS_NAME { typedef TYPE Type; QBasicAtomicInt guard = { QtGlobalStatic::Uninitialized }; __attribute__((visibility ("hidden"))) inline Type *innerFunction() { struct HolderBase { ~HolderBase() noexcept { if (guard.load() == QtGlobalStatic ::Initialized) guard.store(QtGlobalStatic::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept (noexcept(Type ())) : value () { guard.store(QtGlobalStatic:: Initialized); } } holder; return &holder.value; } } } static QGlobalStatic<TYPE, Q_QGS_NAME::innerFunction, Q_QGS_NAME ::guard> NAME; \ |
159 | Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())namespace { namespace Q_QGS_NAME { typedef TYPE Type; QBasicAtomicInt guard = { QtGlobalStatic::Uninitialized }; __attribute__((visibility ("hidden"))) inline Type *innerFunction() { struct HolderBase { ~HolderBase() noexcept { if (guard.load() == QtGlobalStatic ::Initialized) guard.store(QtGlobalStatic::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept (noexcept(Type ())) : value () { guard.store(QtGlobalStatic:: Initialized); } } holder; return &holder.value; } } } static QGlobalStatic<TYPE, Q_QGS_NAME::innerFunction, Q_QGS_NAME ::guard> NAME; |
160 | |
161 | QT_END_NAMESPACE |
162 | #endif // QGLOBALSTATIC_H |
1 | /**************************************************************************** | |||
2 | ** | |||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | |||
4 | ** Contact: https://www.qt.io/licensing/ | |||
5 | ** | |||
6 | ** This file is part of the QtCore module of the Qt Toolkit. | |||
7 | ** | |||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | |||
9 | ** Commercial License Usage | |||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | |||
11 | ** accordance with the commercial license agreement provided with the | |||
12 | ** Software or, alternatively, in accordance with the terms contained in | |||
13 | ** a written agreement between you and The Qt Company. For licensing terms | |||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | |||
15 | ** information use the contact form at https://www.qt.io/contact-us. | |||
16 | ** | |||
17 | ** GNU Lesser General Public License Usage | |||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | |||
19 | ** General Public License version 3 as published by the Free Software | |||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | |||
21 | ** packaging of this file. Please review the following information to | |||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | |||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | |||
24 | ** | |||
25 | ** GNU General Public License Usage | |||
26 | ** Alternatively, this file may be used under the terms of the GNU | |||
27 | ** General Public License version 2.0 or (at your option) the GNU General | |||
28 | ** Public license version 3 or any later version approved by the KDE Free | |||
29 | ** Qt Foundation. The licenses are as published by the Free Software | |||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | |||
31 | ** included in the packaging of this file. Please review the following | |||
32 | ** information to ensure the GNU General Public License requirements will | |||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | |||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | |||
35 | ** | |||
36 | ** $QT_END_LICENSE$ | |||
37 | ** | |||
38 | ****************************************************************************/ | |||
39 | ||||
40 | #ifndef QSHAREDDATA_H | |||
41 | #define QSHAREDDATA_H | |||
42 | ||||
43 | #include <QtCore/qglobal.h> | |||
44 | #include <QtCore/qatomic.h> | |||
45 | #if QT_DEPRECATED_SINCE(5, 6)(((5<<16)|(6<<8)|(0)) > ((5<<16)|(0<< 8)|(0))) | |||
46 | #include <QtCore/qhash.h> | |||
47 | #endif | |||
48 | #include <QtCore/qhashfunctions.h> | |||
49 | ||||
50 | QT_BEGIN_NAMESPACE | |||
51 | ||||
52 | ||||
53 | template <class T> class QSharedDataPointer; | |||
54 | ||||
55 | class Q_CORE_EXPORT__attribute__((visibility("default"))) QSharedData | |||
56 | { | |||
57 | public: | |||
58 | mutable QAtomicInt ref; | |||
59 | ||||
60 | inline QSharedData() : ref(0) { } | |||
61 | inline QSharedData(const QSharedData &) : ref(0) { } | |||
62 | ||||
63 | private: | |||
64 | // using the assignment operator would lead to corruption in the ref-counting | |||
65 | QSharedData &operator=(const QSharedData &); | |||
66 | }; | |||
67 | ||||
68 | template <class T> class QSharedDataPointer | |||
69 | { | |||
70 | public: | |||
71 | typedef T Type; | |||
72 | typedef T *pointer; | |||
73 | ||||
74 | inline void detach() { if (d && d->ref.load() != 1) detach_helper(); } | |||
75 | inline T &operator*() { detach(); return *d; } | |||
76 | inline const T &operator*() const { return *d; } | |||
77 | inline T *operator->() { detach(); return d; } | |||
78 | inline const T *operator->() const { return d; } | |||
79 | inline operator T *() { detach(); return d; } | |||
80 | inline operator const T *() const { return d; } | |||
81 | inline T *data() { detach(); return d; } | |||
82 | inline const T *data() const { return d; } | |||
83 | inline const T *constData() const { return d; } | |||
| ||||
84 | ||||
85 | inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; } | |||
86 | inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; } | |||
87 | ||||
88 | inline QSharedDataPointer() { d = nullptr; } | |||
89 | inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; } | |||
90 | ||||
91 | explicit QSharedDataPointer(T *data) Q_DECL_NOTHROWnoexcept; | |||
92 | inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } | |||
93 | inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) { | |||
94 | if (o.d != d) { | |||
95 | if (o.d) | |||
96 | o.d->ref.ref(); | |||
97 | T *old = d; | |||
98 | d = o.d; | |||
99 | if (old && !old->ref.deref()) | |||
100 | delete old; | |||
101 | } | |||
102 | return *this; | |||
103 | } | |||
104 | inline QSharedDataPointer &operator=(T *o) { | |||
105 | if (o != d) { | |||
106 | if (o) | |||
107 | o->ref.ref(); | |||
108 | T *old = d; | |||
109 | d = o; | |||
110 | if (old && !old->ref.deref()) | |||
111 | delete old; | |||
112 | } | |||
113 | return *this; | |||
114 | } | |||
115 | #ifdef Q_COMPILER_RVALUE_REFS | |||
116 | QSharedDataPointer(QSharedDataPointer &&o) Q_DECL_NOTHROWnoexcept : d(o.d) { o.d = nullptr; } | |||
117 | inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) Q_DECL_NOTHROWnoexcept | |||
118 | { | |||
119 | QSharedDataPointer moved(std::move(other)); | |||
120 | swap(moved); | |||
121 | return *this; | |||
122 | } | |||
123 | #endif | |||
124 | ||||
125 | inline bool operator!() const { return !d; } | |||
126 | ||||
127 | inline void swap(QSharedDataPointer &other) Q_DECL_NOTHROWnoexcept | |||
128 | { qSwap(d, other.d); } | |||
129 | ||||
130 | protected: | |||
131 | T *clone(); | |||
132 | ||||
133 | private: | |||
134 | void detach_helper(); | |||
135 | ||||
136 | T *d; | |||
137 | }; | |||
138 | ||||
139 | template <class T> inline bool operator==(std::nullptr_t p1, const QSharedDataPointer<T> &p2) | |||
140 | { | |||
141 | Q_UNUSED(p1)(void)p1;; | |||
142 | return !p2; | |||
143 | } | |||
144 | ||||
145 | template <class T> inline bool operator==(const QSharedDataPointer<T> &p1, std::nullptr_t p2) | |||
146 | { | |||
147 | Q_UNUSED(p2)(void)p2;; | |||
148 | return !p1; | |||
149 | } | |||
150 | ||||
151 | template <class T> class QExplicitlySharedDataPointer | |||
152 | { | |||
153 | public: | |||
154 | typedef T Type; | |||
155 | typedef T *pointer; | |||
156 | ||||
157 | inline T &operator*() const { return *d; } | |||
158 | inline T *operator->() { return d; } | |||
159 | inline T *operator->() const { return d; } | |||
160 | inline T *data() const { return d; } | |||
161 | inline const T *constData() const { return d; } | |||
162 | inline T *take() { T *x = d; d = nullptr; return x; } | |||
163 | ||||
164 | inline void detach() { if (d && d->ref.load() != 1) detach_helper(); } | |||
165 | ||||
166 | inline void reset() | |||
167 | { | |||
168 | if(d && !d->ref.deref()) | |||
169 | delete d; | |||
170 | ||||
171 | d = nullptr; | |||
172 | } | |||
173 | ||||
174 | inline operator bool () const { return d != nullptr; } | |||
175 | ||||
176 | inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; } | |||
177 | inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; } | |||
178 | inline bool operator==(const T *ptr) const { return d == ptr; } | |||
179 | inline bool operator!=(const T *ptr) const { return d != ptr; } | |||
180 | ||||
181 | inline QExplicitlySharedDataPointer() { d = nullptr; } | |||
182 | inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; } | |||
183 | ||||
184 | explicit QExplicitlySharedDataPointer(T *data) Q_DECL_NOTHROWnoexcept; | |||
185 | inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } | |||
186 | ||||
187 | template<class X> | |||
188 | inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) | |||
189 | #ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST | |||
190 | : d(static_cast<T *>(o.data())) | |||
191 | #else | |||
192 | : d(o.data()) | |||
193 | #endif | |||
194 | { | |||
195 | if(d) | |||
196 | d->ref.ref(); | |||
197 | } | |||
198 | ||||
199 | inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) { | |||
200 | if (o.d != d) { | |||
201 | if (o.d) | |||
202 | o.d->ref.ref(); | |||
203 | T *old = d; | |||
204 | d = o.d; | |||
205 | if (old && !old->ref.deref()) | |||
206 | delete old; | |||
207 | } | |||
208 | return *this; | |||
209 | } | |||
210 | inline QExplicitlySharedDataPointer &operator=(T *o) { | |||
211 | if (o != d) { | |||
212 | if (o) | |||
213 | o->ref.ref(); | |||
214 | T *old = d; | |||
215 | d = o; | |||
216 | if (old && !old->ref.deref()) | |||
217 | delete old; | |||
218 | } | |||
219 | return *this; | |||
220 | } | |||
221 | #ifdef Q_COMPILER_RVALUE_REFS | |||
222 | inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) Q_DECL_NOTHROWnoexcept : d(o.d) { o.d = nullptr; } | |||
223 | inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) Q_DECL_NOTHROWnoexcept | |||
224 | { | |||
225 | QExplicitlySharedDataPointer moved(std::move(other)); | |||
226 | swap(moved); | |||
227 | return *this; | |||
228 | } | |||
229 | #endif | |||
230 | ||||
231 | inline bool operator!() const { return !d; } | |||
232 | ||||
233 | inline void swap(QExplicitlySharedDataPointer &other) Q_DECL_NOTHROWnoexcept | |||
234 | { qSwap(d, other.d); } | |||
235 | ||||
236 | protected: | |||
237 | T *clone(); | |||
238 | ||||
239 | private: | |||
240 | void detach_helper(); | |||
241 | ||||
242 | T *d; | |||
243 | }; | |||
244 | ||||
245 | template <class T> | |||
246 | Q_INLINE_TEMPLATEinline QSharedDataPointer<T>::QSharedDataPointer(T *adata) Q_DECL_NOTHROWnoexcept | |||
247 | : d(adata) | |||
248 | { if (d) d->ref.ref(); } | |||
249 | ||||
250 | template <class T> | |||
251 | Q_INLINE_TEMPLATEinline T *QSharedDataPointer<T>::clone() | |||
252 | { | |||
253 | return new T(*d); | |||
254 | } | |||
255 | ||||
256 | template <class T> | |||
257 | Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper() | |||
258 | { | |||
259 | T *x = clone(); | |||
260 | x->ref.ref(); | |||
261 | if (!d->ref.deref()) | |||
262 | delete d; | |||
263 | d = x; | |||
264 | } | |||
265 | ||||
266 | template <class T> | |||
267 | Q_INLINE_TEMPLATEinline T *QExplicitlySharedDataPointer<T>::clone() | |||
268 | { | |||
269 | return new T(*d); | |||
270 | } | |||
271 | ||||
272 | template <class T> | |||
273 | Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper() | |||
274 | { | |||
275 | T *x = clone(); | |||
276 | x->ref.ref(); | |||
277 | if (!d->ref.deref()) | |||
278 | delete d; | |||
279 | d = x; | |||
280 | } | |||
281 | ||||
282 | template <class T> | |||
283 | Q_INLINE_TEMPLATEinline QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) Q_DECL_NOTHROWnoexcept | |||
284 | : d(adata) | |||
285 | { if (d) d->ref.ref(); } | |||
286 | ||||
287 | template <class T> inline bool operator==(std::nullptr_t p1, const QExplicitlySharedDataPointer<T> &p2) | |||
288 | { | |||
289 | Q_UNUSED(p1)(void)p1;; | |||
290 | return !p2; | |||
291 | } | |||
292 | ||||
293 | template <class T> inline bool operator==(const QExplicitlySharedDataPointer<T> &p1, std::nullptr_t p2) | |||
294 | { | |||
295 | Q_UNUSED(p2)(void)p2;; | |||
296 | return !p1; | |||
297 | } | |||
298 | ||||
299 | template <class T> | |||
300 | Q_INLINE_TEMPLATEinline void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) | |||
301 | { p1.swap(p2); } | |||
302 | ||||
303 | template <class T> | |||
304 | Q_INLINE_TEMPLATEinline void qSwap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) | |||
305 | { p1.swap(p2); } | |||
306 | ||||
307 | QT_END_NAMESPACE | |||
308 | namespace std { | |||
309 | template <class T> | |||
310 | Q_INLINE_TEMPLATEinline void swap(QT_PREPEND_NAMESPACE(QSharedDataPointer)::QSharedDataPointer<T> &p1, QT_PREPEND_NAMESPACE(QSharedDataPointer)::QSharedDataPointer<T> &p2) | |||
311 | { p1.swap(p2); } | |||
312 | ||||
313 | template <class T> | |||
314 | Q_INLINE_TEMPLATEinline void swap(QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)::QExplicitlySharedDataPointer<T> &p1, QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)::QExplicitlySharedDataPointer<T> &p2) | |||
315 | { p1.swap(p2); } | |||
316 | } | |||
317 | QT_BEGIN_NAMESPACE | |||
318 | ||||
319 | template <class T> | |||
320 | Q_INLINE_TEMPLATEinline uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0) Q_DECL_NOTHROWnoexcept | |||
321 | { | |||
322 | return qHash(ptr.data(), seed); | |||
323 | } | |||
324 | template <class T> | |||
325 | Q_INLINE_TEMPLATEinline uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0) Q_DECL_NOTHROWnoexcept | |||
326 | { | |||
327 | return qHash(ptr.data(), seed); | |||
328 | } | |||
329 | ||||
330 | template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE)class QTypeInfo<QSharedDataPointer<T> > { public: enum { isSpecialized = true, isComplex = (((Q_MOVABLE_TYPE) & Q_PRIMITIVE_TYPE) == 0), isStatic = (((Q_MOVABLE_TYPE) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), isRelocatable = ! isStatic || ((Q_MOVABLE_TYPE) & Q_RELOCATABLE_TYPE), isLarge = (sizeof(QSharedDataPointer<T>)>sizeof(void*)), isPointer = false, isIntegral = std::is_integral< QSharedDataPointer <T> >::value, isDummy = (((Q_MOVABLE_TYPE) & Q_DUMMY_TYPE ) != 0), sizeOf = sizeof(QSharedDataPointer<T>) }; static inline const char *name() { return "QSharedDataPointer<T>" ; } }; | |||
331 | template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE)class QTypeInfo<QExplicitlySharedDataPointer<T> > { public: enum { isSpecialized = true, isComplex = (((Q_MOVABLE_TYPE ) & Q_PRIMITIVE_TYPE) == 0), isStatic = (((Q_MOVABLE_TYPE ) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), isRelocatable = !isStatic || ((Q_MOVABLE_TYPE) & Q_RELOCATABLE_TYPE), isLarge = (sizeof(QExplicitlySharedDataPointer<T>)>sizeof(void *)), isPointer = false, isIntegral = std::is_integral< QExplicitlySharedDataPointer <T> >::value, isDummy = (((Q_MOVABLE_TYPE) & Q_DUMMY_TYPE ) != 0), sizeOf = sizeof(QExplicitlySharedDataPointer<T> ) }; static inline const char *name() { return "QExplicitlySharedDataPointer<T>" ; } }; | |||
332 | ||||
333 | QT_END_NAMESPACE | |||
334 | ||||
335 | #endif // QSHAREDDATA_H |
File: | usr/lib64/qt5/include/QtTest/qtestcase.h |
Warning: | line 359, column 9 Potential memory leak |
Press '?' to see keyboard shortcuts
-Keyboard shortcuts:
1 | /* ============================================================ | |||
2 | * | |||
3 | * This file is a part of digiKam project | |||
4 | * https://www.digikam.org | |||
5 | * | |||
6 | * Date : 2013-06-29 | |||
7 | * Description : Test the functions for dealing with DatabaseFields | |||
8 | * | |||
9 | * Copyright (C) 2013 by Michael G. Hansen <mike at mghansen dot de> | |||
10 | * | |||
11 | * This program is free software; you can redistribute it | |||
12 | * and/or modify it under the terms of the GNU General | |||
13 | * Public License as published by the Free Software Foundation; | |||
14 | * either version 2, or (at your option) | |||
15 | * any later version. | |||
16 | * | |||
17 | * This program is distributed in the hope that it will be useful, | |||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
20 | * GNU General Public License for more details. | |||
21 | * | |||
22 | * ============================================================ */ | |||
23 | ||||
24 | #include "databasefieldstest.h" | |||
25 | ||||
26 | // Qt includes | |||
27 | ||||
28 | #include <QTest> | |||
29 | ||||
30 | // Local includes | |||
31 | ||||
32 | #include "coredbfields.h" | |||
33 | ||||
34 | using namespace Digikam; | |||
35 | ||||
36 | QTEST_GUILESS_MAIN(DatabaseFieldsTest)int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); app.setAttribute(Qt::AA_Use96Dpi, true); DatabaseFieldsTest tc; QTest::setMainSourcePath("/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , "/mnt/devel/GIT/6.x/build.scan"); return QTest::qExec(& tc, argc, argv); } | |||
37 | ||||
38 | using namespace DatabaseFields; | |||
39 | ||||
40 | void DatabaseFieldsTest::cleanupTestCase() | |||
41 | { | |||
42 | } | |||
43 | ||||
44 | void DatabaseFieldsTest::initTestCase() | |||
45 | { | |||
46 | } | |||
47 | ||||
48 | #define DECLARE_ITERATOR_TEST(Field){ Field i; for (FieldIterator it; !it.atEnd(); ++it) { i |= * it; } do { if (!QTest::qCompare(i, FieldAll, "i", "FieldAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 48)) return;} while (false); } \ | |||
49 | { \ | |||
50 | Field i; \ | |||
51 | for (Field##Iterator it; !it.atEnd(); ++it) \ | |||
52 | { \ | |||
53 | i |= *it; \ | |||
54 | } \ | |||
55 | QCOMPARE(i, Field##All)do { if (!QTest::qCompare(i, Field##All, "i", "Field##All", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 55)) return;} while (false); \ | |||
56 | } | |||
57 | ||||
58 | void DatabaseFieldsTest::testIterators() | |||
59 | { | |||
60 | // test that the iterator iterates over all fields | |||
61 | DECLARE_ITERATOR_TEST(Images){ Images i; for (ImagesIterator it; !it.atEnd(); ++it) { i |= *it; } do { if (!QTest::qCompare(i, ImagesAll, "i", "ImagesAll" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 61)) return;} while (false); } | |||
62 | DECLARE_ITERATOR_TEST(ItemInformation){ ItemInformation i; for (ItemInformationIterator it; !it.atEnd (); ++it) { i |= *it; } do { if (!QTest::qCompare(i, ItemInformationAll , "i", "ItemInformationAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 62)) return;} while (false); } | |||
63 | DECLARE_ITERATOR_TEST(ImageMetadata){ ImageMetadata i; for (ImageMetadataIterator it; !it.atEnd() ; ++it) { i |= *it; } do { if (!QTest::qCompare(i, ImageMetadataAll , "i", "ImageMetadataAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 63)) return;} while (false); } | |||
64 | DECLARE_ITERATOR_TEST(VideoMetadata){ VideoMetadata i; for (VideoMetadataIterator it; !it.atEnd() ; ++it) { i |= *it; } do { if (!QTest::qCompare(i, VideoMetadataAll , "i", "VideoMetadataAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 64)) return;} while (false); } | |||
65 | DECLARE_ITERATOR_TEST(ItemPositions){ ItemPositions i; for (ItemPositionsIterator it; !it.atEnd() ; ++it) { i |= *it; } do { if (!QTest::qCompare(i, ItemPositionsAll , "i", "ItemPositionsAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 65)) return;} while (false); } | |||
66 | DECLARE_ITERATOR_TEST(ItemComments){ ItemComments i; for (ItemCommentsIterator it; !it.atEnd(); ++ it) { i |= *it; } do { if (!QTest::qCompare(i, ItemCommentsAll , "i", "ItemCommentsAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 66)) return;} while (false); } | |||
67 | DECLARE_ITERATOR_TEST(ImageHistoryInfo){ ImageHistoryInfo i; for (ImageHistoryInfoIterator it; !it.atEnd (); ++it) { i |= *it; } do { if (!QTest::qCompare(i, ImageHistoryInfoAll , "i", "ImageHistoryInfoAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 67)) return;} while (false); } | |||
68 | } | |||
69 | ||||
70 | void DatabaseFieldsTest::testMetaInfo() | |||
71 | { | |||
72 | // Do not compile due to undefined reference to `Digikam::DatabaseFields::FieldMetaInfo<QFlags<Digikam::DatabaseFields::ImagesField> >::Last' | |||
73 | // Happens even though file defining those libs/database/framework/databasefields.h is included and linking against digikamgui. | |||
74 | ||||
75 | ||||
76 | /* | |||
77 | QCOMPARE(FieldMetaInfo<Images>::Last, ImagesLast); | |||
78 | QCOMPARE(FieldMetaInfo<ItemInformation>::Last, ItemInformationLast); | |||
79 | QCOMPARE(FieldMetaInfo<ImageMetadata>::Last, ImageMetadataLast); | |||
80 | QCOMPARE(FieldMetaInfo<ItemComments>::Last, ItemCommentsLast); | |||
81 | QCOMPARE(FieldMetaInfo<ItemPositions>::Last, ItemPositionsLast); | |||
82 | QCOMPARE(FieldMetaInfo<ImageHistoryInfo>::Last, ImageHistoryInfoLast); | |||
83 | QCOMPARE(FieldMetaInfo<VideoMetadata>::Last, VideoMetadataLast); | |||
84 | */ | |||
85 | } | |||
86 | ||||
87 | #define DECLARE_ITERATORSETONLY_TEST(Field)for (Field i = FieldNone; i<=FieldAll; i=Field(int(i)+1)) { Field i2 = FieldNone; for (DatabaseFieldsEnumIteratorSetOnly <Field> iOnly(i); !iOnly.atEnd(); ++iOnly) { i2 |= *iOnly ; } do { if (!QTest::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 87)) return;} while (false); } \ | |||
88 | for (Field i = Field##None; i<=Field##All; i=Field(int(i)+1)) \ | |||
89 | { \ | |||
90 | Field i2 = Field##None; \ | |||
91 | for (DatabaseFieldsEnumIteratorSetOnly<Field> iOnly(i); !iOnly.atEnd(); ++iOnly) \ | |||
92 | { \ | |||
93 | i2 |= *iOnly; \ | |||
94 | } \ | |||
95 | QCOMPARE(i, i2)do { if (!QTest::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 95)) return;} while (false); \ | |||
96 | } | |||
97 | ||||
98 | void DatabaseFieldsTest::testIteratorsSetOnly() | |||
99 | { | |||
100 | DECLARE_ITERATORSETONLY_TEST(Images)for (Images i = ImagesNone; i<=ImagesAll; i=Images(int(i)+ 1)) { Images i2 = ImagesNone; for (DatabaseFieldsEnumIteratorSetOnly <Images> iOnly(i); !iOnly.atEnd(); ++iOnly) { i2 |= *iOnly ; } do { if (!QTest::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 100)) return;} while (false); } | |||
| ||||
101 | DECLARE_ITERATORSETONLY_TEST(ItemInformation)for (ItemInformation i = ItemInformationNone; i<=ItemInformationAll ; i=ItemInformation(int(i)+1)) { ItemInformation i2 = ItemInformationNone ; for (DatabaseFieldsEnumIteratorSetOnly<ItemInformation> iOnly(i); !iOnly.atEnd(); ++iOnly) { i2 |= *iOnly; } do { if (!QTest::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 101)) return;} while (false); } | |||
102 | DECLARE_ITERATORSETONLY_TEST(ImageMetadata)for (ImageMetadata i = ImageMetadataNone; i<=ImageMetadataAll ; i=ImageMetadata(int(i)+1)) { ImageMetadata i2 = ImageMetadataNone ; for (DatabaseFieldsEnumIteratorSetOnly<ImageMetadata> iOnly(i); !iOnly.atEnd(); ++iOnly) { i2 |= *iOnly; } do { if (!QTest::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 102)) return;} while (false); } | |||
103 | DECLARE_ITERATORSETONLY_TEST(VideoMetadata)for (VideoMetadata i = VideoMetadataNone; i<=VideoMetadataAll ; i=VideoMetadata(int(i)+1)) { VideoMetadata i2 = VideoMetadataNone ; for (DatabaseFieldsEnumIteratorSetOnly<VideoMetadata> iOnly(i); !iOnly.atEnd(); ++iOnly) { i2 |= *iOnly; } do { if (!QTest::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 103)) return;} while (false); } | |||
104 | DECLARE_ITERATORSETONLY_TEST(ItemPositions)for (ItemPositions i = ItemPositionsNone; i<=ItemPositionsAll ; i=ItemPositions(int(i)+1)) { ItemPositions i2 = ItemPositionsNone ; for (DatabaseFieldsEnumIteratorSetOnly<ItemPositions> iOnly(i); !iOnly.atEnd(); ++iOnly) { i2 |= *iOnly; } do { if (!QTest::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 104)) return;} while (false); } | |||
105 | DECLARE_ITERATORSETONLY_TEST(ItemComments)for (ItemComments i = ItemCommentsNone; i<=ItemCommentsAll ; i=ItemComments(int(i)+1)) { ItemComments i2 = ItemCommentsNone ; for (DatabaseFieldsEnumIteratorSetOnly<ItemComments> iOnly (i); !iOnly.atEnd(); ++iOnly) { i2 |= *iOnly; } do { if (!QTest ::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 105)) return;} while (false); } | |||
106 | DECLARE_ITERATORSETONLY_TEST(ImageHistoryInfo)for (ImageHistoryInfo i = ImageHistoryInfoNone; i<=ImageHistoryInfoAll ; i=ImageHistoryInfo(int(i)+1)) { ImageHistoryInfo i2 = ImageHistoryInfoNone ; for (DatabaseFieldsEnumIteratorSetOnly<ImageHistoryInfo> iOnly(i); !iOnly.atEnd(); ++iOnly) { i2 |= *iOnly; } do { if (!QTest::qCompare(i, i2, "i", "i2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 106)) return;} while (false); } | |||
107 | } | |||
108 | ||||
109 | void DatabaseFieldsTest::testSet() | |||
110 | { | |||
111 | QCOMPARE(Set(ImagesFirst).getImages(), ImagesFirst)do { if (!QTest::qCompare(Set(ImagesFirst).getImages(), ImagesFirst , "Set(ImagesFirst).getImages()", "ImagesFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 111)) return;} while (false); | |||
112 | QCOMPARE(Set(ItemInformationFirst).getItemInformation(), ItemInformationFirst)do { if (!QTest::qCompare(Set(ItemInformationFirst).getItemInformation (), ItemInformationFirst, "Set(ItemInformationFirst).getItemInformation()" , "ItemInformationFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 112)) return;} while (false); | |||
113 | QCOMPARE(Set(ImageMetadataFirst).getImageMetadata(), ImageMetadataFirst)do { if (!QTest::qCompare(Set(ImageMetadataFirst).getImageMetadata (), ImageMetadataFirst, "Set(ImageMetadataFirst).getImageMetadata()" , "ImageMetadataFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 113)) return;} while (false); | |||
114 | QCOMPARE(Set(VideoMetadataFirst).getVideoMetadata(), VideoMetadataFirst)do { if (!QTest::qCompare(Set(VideoMetadataFirst).getVideoMetadata (), VideoMetadataFirst, "Set(VideoMetadataFirst).getVideoMetadata()" , "VideoMetadataFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 114)) return;} while (false); | |||
115 | QCOMPARE(Set(ItemPositionsFirst).getItemPositions(), ItemPositionsFirst)do { if (!QTest::qCompare(Set(ItemPositionsFirst).getItemPositions (), ItemPositionsFirst, "Set(ItemPositionsFirst).getItemPositions()" , "ItemPositionsFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 115)) return;} while (false); | |||
116 | QCOMPARE(Set(ItemCommentsFirst).getItemComments(), ItemCommentsFirst)do { if (!QTest::qCompare(Set(ItemCommentsFirst).getItemComments (), ItemCommentsFirst, "Set(ItemCommentsFirst).getItemComments()" , "ItemCommentsFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 116)) return;} while (false); | |||
117 | QCOMPARE(Set(ImageHistoryInfoFirst).getImageHistoryInfo(), ImageHistoryInfoFirst)do { if (!QTest::qCompare(Set(ImageHistoryInfoFirst).getImageHistoryInfo (), ImageHistoryInfoFirst, "Set(ImageHistoryInfoFirst).getImageHistoryInfo()" , "ImageHistoryInfoFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 117)) return;} while (false); | |||
118 | } | |||
119 | ||||
120 | typedef Hash<Set> SetHash; | |||
121 | ||||
122 | SetHash SetHashAddSets(const SetHash& targetIn, const Set& bits) | |||
123 | { | |||
124 | SetHash target(targetIn); | |||
125 | ||||
126 | for (DatabaseFieldsEnumIteratorSetOnly<Images> it(bits.getImages()); !it.atEnd(); ++it) | |||
127 | { | |||
128 | target.insertField(*it, Set(*it)); | |||
129 | } | |||
130 | ||||
131 | for (DatabaseFieldsEnumIteratorSetOnly<ItemInformation> it(bits.getItemInformation()); !it.atEnd(); ++it) | |||
132 | { | |||
133 | target.insertField(*it, Set(*it)); | |||
134 | } | |||
135 | ||||
136 | for (DatabaseFieldsEnumIteratorSetOnly<ImageMetadata> it(bits.getImageMetadata()); !it.atEnd(); ++it) | |||
137 | { | |||
138 | target.insertField(*it, Set(*it)); | |||
139 | } | |||
140 | ||||
141 | for (DatabaseFieldsEnumIteratorSetOnly<VideoMetadata> it(bits.getVideoMetadata()); !it.atEnd(); ++it) | |||
142 | { | |||
143 | target.insertField(*it, Set(*it)); | |||
144 | } | |||
145 | ||||
146 | for (DatabaseFieldsEnumIteratorSetOnly<ItemComments> it(bits.getItemComments()); !it.atEnd(); ++it) | |||
147 | { | |||
148 | target.insertField(*it, Set(*it)); | |||
149 | } | |||
150 | ||||
151 | for (DatabaseFieldsEnumIteratorSetOnly<ItemPositions> it(bits.getItemPositions()); !it.atEnd(); ++it) | |||
152 | { | |||
153 | target.insertField(*it, Set(*it)); | |||
154 | } | |||
155 | ||||
156 | for (DatabaseFieldsEnumIteratorSetOnly<ImageHistoryInfo> it(bits.getImageHistoryInfo()); !it.atEnd(); ++it) | |||
157 | { | |||
158 | target.insertField(*it, Set(*it)); | |||
159 | } | |||
160 | ||||
161 | return target; | |||
162 | } | |||
163 | ||||
164 | void DatabaseFieldsTest::testSetHashAddSets() | |||
165 | { | |||
166 | SetHash t; | |||
167 | int itemCount = 0; | |||
168 | ||||
169 | QVERIFY(t.isEmpty())do { if (!QTest::qVerify(static_cast<bool>(t.isEmpty()) , "t.isEmpty()", "", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 169)) return;} while (false); | |||
170 | t = SetHashAddSets(t, DatabaseFields::Set(ImagesFirst)); | |||
171 | ++itemCount; | |||
172 | QCOMPARE(t.size(), itemCount)do { if (!QTest::qCompare(t.size(), itemCount, "t.size()", "itemCount" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 172)) return;} while (false); | |||
173 | QCOMPARE(t.value(ImagesFirst).getImages(), ImagesFirst)do { if (!QTest::qCompare(t.value(ImagesFirst).getImages(), ImagesFirst , "t.value(ImagesFirst).getImages()", "ImagesFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 173)) return;} while (false); | |||
174 | ||||
175 | t = SetHashAddSets(t, DatabaseFields::Set(ImagesLast)); | |||
176 | ++itemCount; | |||
177 | QCOMPARE(t.size(), itemCount)do { if (!QTest::qCompare(t.size(), itemCount, "t.size()", "itemCount" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 177)) return;} while (false); | |||
178 | QCOMPARE(t.value(ImagesFirst).getImages(), ImagesFirst)do { if (!QTest::qCompare(t.value(ImagesFirst).getImages(), ImagesFirst , "t.value(ImagesFirst).getImages()", "ImagesFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 178)) return;} while (false); | |||
179 | ||||
180 | // test insertion of or`ed values | |||
181 | t = SetHashAddSets(t, DatabaseFields::Set(ItemInformationFirst | ItemInformationLast)); | |||
182 | itemCount+=2; | |||
183 | QCOMPARE(t.size(), itemCount)do { if (!QTest::qCompare(t.size(), itemCount, "t.size()", "itemCount" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 183)) return;} while (false); | |||
184 | QCOMPARE(t.value(ItemInformationFirst).getItemInformation(), ItemInformationFirst)do { if (!QTest::qCompare(t.value(ItemInformationFirst).getItemInformation (), ItemInformationFirst, "t.value(ItemInformationFirst).getItemInformation()" , "ItemInformationFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 184)) return;} while (false); | |||
185 | QCOMPARE(t.value(ItemInformationLast).getItemInformation(), ItemInformationLast)do { if (!QTest::qCompare(t.value(ItemInformationLast).getItemInformation (), ItemInformationLast, "t.value(ItemInformationLast).getItemInformation()" , "ItemInformationLast", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 185)) return;} while (false); | |||
186 | ||||
187 | t = SetHashAddSets(t, DatabaseFields::Set(ImageMetadataFirst)); | |||
188 | ++itemCount; | |||
189 | QCOMPARE(t.size(), itemCount)do { if (!QTest::qCompare(t.size(), itemCount, "t.size()", "itemCount" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 189)) return;} while (false); | |||
190 | QCOMPARE(t.value(ImageMetadataFirst).getImageMetadata(), ImageMetadataFirst)do { if (!QTest::qCompare(t.value(ImageMetadataFirst).getImageMetadata (), ImageMetadataFirst, "t.value(ImageMetadataFirst).getImageMetadata()" , "ImageMetadataFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 190)) return;} while (false); | |||
191 | ||||
192 | t = SetHashAddSets(t, DatabaseFields::Set(VideoMetadataFirst)); | |||
193 | ++itemCount; | |||
194 | QCOMPARE(t.size(), itemCount)do { if (!QTest::qCompare(t.size(), itemCount, "t.size()", "itemCount" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 194)) return;} while (false); | |||
195 | QCOMPARE(t.value(VideoMetadataFirst).getVideoMetadata(), VideoMetadataFirst)do { if (!QTest::qCompare(t.value(VideoMetadataFirst).getVideoMetadata (), VideoMetadataFirst, "t.value(VideoMetadataFirst).getVideoMetadata()" , "VideoMetadataFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 195)) return;} while (false); | |||
196 | ||||
197 | t = SetHashAddSets(t, DatabaseFields::Set(ItemCommentsFirst)); | |||
198 | ++itemCount; | |||
199 | QCOMPARE(t.size(), itemCount)do { if (!QTest::qCompare(t.size(), itemCount, "t.size()", "itemCount" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 199)) return;} while (false); | |||
200 | QCOMPARE(t.value(ItemCommentsFirst).getItemComments(), ItemCommentsFirst)do { if (!QTest::qCompare(t.value(ItemCommentsFirst).getItemComments (), ItemCommentsFirst, "t.value(ItemCommentsFirst).getItemComments()" , "ItemCommentsFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 200)) return;} while (false); | |||
201 | ||||
202 | t = SetHashAddSets(t, DatabaseFields::Set(ItemPositionsFirst)); | |||
203 | ++itemCount; | |||
204 | QCOMPARE(t.size(), itemCount)do { if (!QTest::qCompare(t.size(), itemCount, "t.size()", "itemCount" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 204)) return;} while (false); | |||
205 | QCOMPARE(t.value(ItemPositionsFirst).getItemPositions(), ItemPositionsFirst)do { if (!QTest::qCompare(t.value(ItemPositionsFirst).getItemPositions (), ItemPositionsFirst, "t.value(ItemPositionsFirst).getItemPositions()" , "ItemPositionsFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 205)) return;} while (false); | |||
206 | ||||
207 | t = SetHashAddSets(t, DatabaseFields::Set(ImageHistoryInfoFirst)); | |||
208 | ++itemCount; | |||
209 | QCOMPARE(t.size(), itemCount)do { if (!QTest::qCompare(t.size(), itemCount, "t.size()", "itemCount" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 209)) return;} while (false); | |||
210 | QCOMPARE(t.value(ImageHistoryInfoFirst).getImageHistoryInfo(), ImageHistoryInfoFirst)do { if (!QTest::qCompare(t.value(ImageHistoryInfoFirst).getImageHistoryInfo (), ImageHistoryInfoFirst, "t.value(ImageHistoryInfoFirst).getImageHistoryInfo()" , "ImageHistoryInfoFirst", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 210)) return;} while (false); | |||
211 | } | |||
212 | ||||
213 | ||||
214 | void DatabaseFieldsTest::testHashRemoveAll() | |||
215 | { | |||
216 | Set setToAdd = | |||
217 | Set(DatabaseFields::Set(ImagesFirst | ImagesLast)) | |||
218 | .setFields(DatabaseFields::Set(ItemInformationFirst)) | |||
219 | .setFields(DatabaseFields::Set(ImageMetadataFirst)) | |||
220 | .setFields(DatabaseFields::Set(VideoMetadataFirst)) | |||
221 | .setFields(DatabaseFields::Set(ItemCommentsFirst)) | |||
222 | .setFields(DatabaseFields::Set(ItemPositionsFirst | ItemPositionsLast)) | |||
223 | .setFields(DatabaseFields::Set(ImageHistoryInfoFirst)); | |||
224 | ||||
225 | SetHash t; | |||
226 | t = SetHashAddSets(t, setToAdd); | |||
227 | ||||
228 | const int c1 = t.size(); | |||
229 | ||||
230 | // test regular remove | |||
231 | SetHash t2(t); | |||
232 | QCOMPARE(t2.remove(ImagesFirst), 1)do { if (!QTest::qCompare(t2.remove(ImagesFirst), 1, "t2.remove(ImagesFirst)" , "1", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 232)) return;} while (false); | |||
233 | QCOMPARE(t2.size(), c1-1)do { if (!QTest::qCompare(t2.size(), c1-1, "t2.size()", "c1-1" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 233)) return;} while (false); | |||
234 | ||||
235 | // test removeAllFields: First and Last are in the hash, None is not --> 2 entries should be removed | |||
236 | SetHash t3(t); | |||
237 | QCOMPARE(t3.removeAllFields(ImagesFirst | ImagesLast | ImagesNone), 2)do { if (!QTest::qCompare(t3.removeAllFields(ImagesFirst | ImagesLast | ImagesNone), 2, "t3.removeAllFields(ImagesFirst | ImagesLast | ImagesNone)" , "2", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 237)) return;} while (false); | |||
238 | QCOMPARE(t3.size(), c1-2)do { if (!QTest::qCompare(t3.size(), c1-2, "t3.size()", "c1-2" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 238)) return;} while (false); | |||
239 | } | |||
240 | ||||
241 | #define DECLARE_MINSIZE_TEST(FieldName){ const FieldMetaInfo<FieldName>::MinSizeType m = FieldNameAll ; const FieldName v = FieldMetaInfo<FieldName>::fromMinSizeType (m); do { if (!QTest::qCompare(v, FieldNameAll, "v", "FieldNameAll" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 241)) return;} while (false); } \ | |||
242 | { \ | |||
243 | const FieldMetaInfo<FieldName>::MinSizeType m = FieldName##All; \ | |||
244 | const FieldName v = FieldMetaInfo<FieldName>::fromMinSizeType(m); \ | |||
245 | QCOMPARE(v, FieldName##All)do { if (!QTest::qCompare(v, FieldName##All, "v", "FieldName##All" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 245)) return;} while (false); \ | |||
246 | } | |||
247 | ||||
248 | /** | |||
249 | * Verify that the minimum size types still hold all info of the enum. | |||
250 | */ | |||
251 | void DatabaseFieldsTest::testMinSizeType() | |||
252 | { | |||
253 | DECLARE_MINSIZE_TEST(Images){ const FieldMetaInfo<Images>::MinSizeType m = ImagesAll ; const Images v = FieldMetaInfo<Images>::fromMinSizeType (m); do { if (!QTest::qCompare(v, ImagesAll, "v", "ImagesAll" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 253)) return;} while (false); } | |||
254 | DECLARE_MINSIZE_TEST(ItemInformation){ const FieldMetaInfo<ItemInformation>::MinSizeType m = ItemInformationAll; const ItemInformation v = FieldMetaInfo< ItemInformation>::fromMinSizeType(m); do { if (!QTest::qCompare (v, ItemInformationAll, "v", "ItemInformationAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 254)) return;} while (false); } | |||
255 | DECLARE_MINSIZE_TEST(ImageMetadata){ const FieldMetaInfo<ImageMetadata>::MinSizeType m = ImageMetadataAll ; const ImageMetadata v = FieldMetaInfo<ImageMetadata>:: fromMinSizeType(m); do { if (!QTest::qCompare(v, ImageMetadataAll , "v", "ImageMetadataAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 255)) return;} while (false); } | |||
256 | DECLARE_MINSIZE_TEST(ItemComments){ const FieldMetaInfo<ItemComments>::MinSizeType m = ItemCommentsAll ; const ItemComments v = FieldMetaInfo<ItemComments>::fromMinSizeType (m); do { if (!QTest::qCompare(v, ItemCommentsAll, "v", "ItemCommentsAll" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 256)) return;} while (false); } | |||
257 | DECLARE_MINSIZE_TEST(ItemPositions){ const FieldMetaInfo<ItemPositions>::MinSizeType m = ItemPositionsAll ; const ItemPositions v = FieldMetaInfo<ItemPositions>:: fromMinSizeType(m); do { if (!QTest::qCompare(v, ItemPositionsAll , "v", "ItemPositionsAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 257)) return;} while (false); } | |||
258 | DECLARE_MINSIZE_TEST(ImageHistoryInfo){ const FieldMetaInfo<ImageHistoryInfo>::MinSizeType m = ImageHistoryInfoAll; const ImageHistoryInfo v = FieldMetaInfo <ImageHistoryInfo>::fromMinSizeType(m); do { if (!QTest ::qCompare(v, ImageHistoryInfoAll, "v", "ImageHistoryInfoAll" , "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 258)) return;} while (false); } | |||
259 | DECLARE_MINSIZE_TEST(VideoMetadata){ const FieldMetaInfo<VideoMetadata>::MinSizeType m = VideoMetadataAll ; const VideoMetadata v = FieldMetaInfo<VideoMetadata>:: fromMinSizeType(m); do { if (!QTest::qCompare(v, VideoMetadataAll , "v", "VideoMetadataAll", "/mnt/devel/GIT/6.x/core/tests/database/databasefieldstest.cpp" , 259)) return;} while (false); } | |||
260 | } |
1 | /**************************************************************************** | |||
2 | ** | |||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | |||
4 | ** Contact: https://www.qt.io/licensing/ | |||
5 | ** | |||
6 | ** This file is part of the QtTest module of the Qt Toolkit. | |||
7 | ** | |||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | |||
9 | ** Commercial License Usage | |||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | |||
11 | ** accordance with the commercial license agreement provided with the | |||
12 | ** Software or, alternatively, in accordance with the terms contained in | |||
13 | ** a written agreement between you and The Qt Company. For licensing terms | |||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | |||
15 | ** information use the contact form at https://www.qt.io/contact-us. | |||
16 | ** | |||
17 | ** GNU Lesser General Public License Usage | |||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | |||
19 | ** General Public License version 3 as published by the Free Software | |||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | |||
21 | ** packaging of this file. Please review the following information to | |||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | |||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | |||
24 | ** | |||
25 | ** GNU General Public License Usage | |||
26 | ** Alternatively, this file may be used under the terms of the GNU | |||
27 | ** General Public License version 2.0 or (at your option) the GNU General | |||
28 | ** Public license version 3 or any later version approved by the KDE Free | |||
29 | ** Qt Foundation. The licenses are as published by the Free Software | |||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | |||
31 | ** included in the packaging of this file. Please review the following | |||
32 | ** information to ensure the GNU General Public License requirements will | |||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | |||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | |||
35 | ** | |||
36 | ** $QT_END_LICENSE$ | |||
37 | ** | |||
38 | ****************************************************************************/ | |||
39 | ||||
40 | #ifndef QTESTCASE_H | |||
41 | #define QTESTCASE_H | |||
42 | ||||
43 | #include <QtTest/qttestglobal.h> | |||
44 | ||||
45 | #include <QtCore/qstring.h> | |||
46 | #include <QtCore/qnamespace.h> | |||
47 | #include <QtCore/qmetatype.h> | |||
48 | #include <QtCore/qmetaobject.h> | |||
49 | #include <QtCore/qsharedpointer.h> | |||
50 | #include <QtCore/qtemporarydir.h> | |||
51 | ||||
52 | #include <string.h> | |||
53 | ||||
54 | #ifndef QT_NO_EXCEPTIONS | |||
55 | # include <exception> | |||
56 | #endif // QT_NO_EXCEPTIONS | |||
57 | ||||
58 | QT_BEGIN_NAMESPACE | |||
59 | ||||
60 | class QRegularExpression; | |||
61 | ||||
62 | #define QVERIFY(statement)do { if (!QTest::qVerify(static_cast<bool>(statement), "statement" , "", "/usr/lib64/qt5/include/QtTest/qtestcase.h", 62)) return ;} while (false) \ | |||
63 | do {\ | |||
64 | if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__64))\ | |||
65 | return;\ | |||
66 | } while (false) | |||
67 | ||||
68 | #define QFAIL(message)do { QTest::qFail(message, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 68); return;} while (false) \ | |||
69 | do {\ | |||
70 | QTest::qFail(message, __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__70);\ | |||
71 | return;\ | |||
72 | } while (false) | |||
73 | ||||
74 | #define QVERIFY2(statement, description)do { if (statement) { if (!QTest::qVerify(true, "statement", ( description), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 74 )) return; } else { if (!QTest::qVerify(false, "statement", ( description), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 74 )) return; }} while (false) \ | |||
75 | do {\ | |||
76 | if (statement) {\ | |||
77 | if (!QTest::qVerify(true, #statement, (description), __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__77))\ | |||
78 | return;\ | |||
79 | } else {\ | |||
80 | if (!QTest::qVerify(false, #statement, (description), __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__80))\ | |||
81 | return;\ | |||
82 | }\ | |||
83 | } while (false) | |||
84 | ||||
85 | #define QCOMPARE(actual, expected)do { if (!QTest::qCompare(actual, expected, "actual", "expected" , "/usr/lib64/qt5/include/QtTest/qtestcase.h", 85)) return;} while (false) \ | |||
86 | do {\ | |||
87 | if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__87))\ | |||
88 | return;\ | |||
89 | } while (false) | |||
90 | ||||
91 | ||||
92 | #ifndef QT_NO_EXCEPTIONS | |||
93 | ||||
94 | # define QVERIFY_EXCEPTION_THROWN(expression, exceptiontype)do { try { try { expression; QTest::qFail("Expected exception of type " "exceptiontype" " to be thrown" " but no exception caught", "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 94); return; } catch (const exceptiontype &) { } } catch (const std::exception &e) { QByteArray msg = QByteArray( ) + "Expected exception of type " "exceptiontype" " to be thrown but std::exception caught with message: " + e.what(); QTest::qFail(msg.constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 94); return; } catch (...) { QTest::qFail("Expected exception of type " "exceptiontype" " to be thrown" " but unknown exception caught" , "/usr/lib64/qt5/include/QtTest/qtestcase.h", 94); return; } } while (false) \ | |||
95 | do {\ | |||
96 | QT_TRYtry {\ | |||
97 | QT_TRYtry {\ | |||
98 | expression;\ | |||
99 | QTest::qFail("Expected exception of type " #exceptiontype " to be thrown" \ | |||
100 | " but no exception caught", __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__100);\ | |||
101 | return;\ | |||
102 | } QT_CATCH (const exceptiontype &)catch (const exceptiontype &) {\ | |||
103 | }\ | |||
104 | } QT_CATCH (const std::exception &e)catch (const std::exception &e) {\ | |||
105 | QByteArray msg = QByteArray() + "Expected exception of type " #exceptiontype \ | |||
106 | " to be thrown but std::exception caught with message: " + e.what(); \ | |||
107 | QTest::qFail(msg.constData(), __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__107);\ | |||
108 | return;\ | |||
109 | } QT_CATCH (...)catch (...) {\ | |||
110 | QTest::qFail("Expected exception of type " #exceptiontype " to be thrown" \ | |||
111 | " but unknown exception caught", __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__111);\ | |||
112 | return;\ | |||
113 | }\ | |||
114 | } while (false) | |||
115 | ||||
116 | #else // QT_NO_EXCEPTIONS | |||
117 | ||||
118 | /* | |||
119 | * The expression passed to the macro should throw an exception and we can't | |||
120 | * catch it because Qt has been compiled without exception support. We can't | |||
121 | * skip the expression because it may have side effects and must be executed. | |||
122 | * So, users must use Qt with exception support enabled if they use exceptions | |||
123 | * in their code. | |||
124 | */ | |||
125 | # define QVERIFY_EXCEPTION_THROWN(expression, exceptiontype)do { try { try { expression; QTest::qFail("Expected exception of type " "exceptiontype" " to be thrown" " but no exception caught", "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 125); return; } catch (const exceptiontype &) { } } catch (const std::exception &e) { QByteArray msg = QByteArray( ) + "Expected exception of type " "exceptiontype" " to be thrown but std::exception caught with message: " + e.what(); QTest::qFail(msg.constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 125); return; } catch (...) { QTest::qFail("Expected exception of type " "exceptiontype" " to be thrown" " but unknown exception caught" , "/usr/lib64/qt5/include/QtTest/qtestcase.h", 125); return; } } while (false) \ | |||
126 | Q_STATIC_ASSERT_X(false, "Support of exceptions is disabled")static_assert(bool(false), "Support of exceptions is disabled" ) | |||
127 | ||||
128 | #endif // !QT_NO_EXCEPTIONS | |||
129 | ||||
130 | ||||
131 | #define QTRY_LOOP_IMPL(expr, timeoutValue, step)if (!(expr)) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < timeoutValue && !(expr); qt_test_i += step) { QTest ::qWait(step); } \ | |||
132 | if (!(expr)) { \ | |||
133 | QTest::qWait(0); \ | |||
134 | } \ | |||
135 | int qt_test_i = 0; \ | |||
136 | for (; qt_test_i < timeoutValue && !(expr); qt_test_i += step) { \ | |||
137 | QTest::qWait(step); \ | |||
138 | } | |||
139 | ||||
140 | #define QTRY_TIMEOUT_DEBUG_IMPL(expr, timeoutValue, step)if (!(expr)) { if (!((expr))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * timeoutValue) && !(( expr)); qt_test_i += step) { QTest::qWait(step); }; if (expr) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("expr")).arg(timeoutValue) .arg(timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate:: asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 140); return;} while (false); } }\ | |||
141 | if (!(expr)) { \ | |||
142 | QTRY_LOOP_IMPL((expr), (2 * timeoutValue), step)if (!((expr))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * timeoutValue) && !((expr)); qt_test_i += step) { QTest::qWait(step); };\ | |||
143 | if (expr) { \ | |||
144 | QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time."); \ | |||
145 | msg = msg.arg(QString::fromUtf8(#expr)).arg(timeoutValue).arg(timeoutValue + qt_test_i); \ | |||
146 | QFAIL(qPrintable(msg))do { QTest::qFail(QtPrivate::asString(msg).toLocal8Bit().constData (), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 146); return ;} while (false); \ | |||
147 | } \ | |||
148 | } | |||
149 | ||||
150 | // Ideally we'd use qWaitFor instead of QTRY_LOOP_IMPL, but due | |||
151 | // to a compiler bug on MSVC < 2017 we can't (see QTBUG-59096) | |||
152 | #define QTRY_IMPL(expr, timeout)const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; const int qt_test_timeoutValue = timeout; if (!((expr))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !((expr)); qt_test_i += qt_test_step ) { QTest::qWait(qt_test_step); }; if (!((expr))) { if (!(((expr )))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !(((expr))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if ((expr) ) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("(expr)")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 152); return;} while (false); } }\ | |||
153 | const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; \ | |||
154 | const int qt_test_timeoutValue = timeout; \ | |||
155 | QTRY_LOOP_IMPL((expr), qt_test_timeoutValue, qt_test_step)if (!((expr))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !((expr)); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; \ | |||
156 | QTRY_TIMEOUT_DEBUG_IMPL((expr), qt_test_timeoutValue, qt_test_step)if (!((expr))) { if (!(((expr)))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !(((expr))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step ); }; if ((expr)) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("(expr)")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 156); return;} while (false); } }\ | |||
157 | ||||
158 | // Will try to wait for the expression to become true while allowing event processing | |||
159 | #define QTRY_VERIFY_WITH_TIMEOUT(expr, timeout)do { const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; const int qt_test_timeoutValue = timeout; if (!(((expr )))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !(((expr))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if (!(((expr) ))) { if (!((((expr))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !((((expr)))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step ); }; if (((expr))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("((expr))")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 159); return;} while (false); } }; do { if (!QTest::qVerify (static_cast<bool>(expr), "expr", "", "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 159)) return;} while (false); } while (false) \ | |||
160 | do { \ | |||
161 | QTRY_IMPL((expr), timeout)const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; const int qt_test_timeoutValue = timeout; if (!(((expr)) )) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !(((expr))); qt_test_i += qt_test_step ) { QTest::qWait(qt_test_step); }; if (!(((expr)))) { if (!(( ((expr))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !((((expr)))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if (((expr ))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("((expr))")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 161); return;} while (false); } };\ | |||
162 | QVERIFY(expr)do { if (!QTest::qVerify(static_cast<bool>(expr), "expr" , "", "/usr/lib64/qt5/include/QtTest/qtestcase.h", 162)) return ;} while (false); \ | |||
163 | } while (false) | |||
164 | ||||
165 | #define QTRY_VERIFY(expr)do { const int qt_test_step = 5000 < 350 ? 5000 / 7 + 1 : 50 ; const int qt_test_timeoutValue = 5000; if (!((((expr))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !((((expr)))); qt_test_i += qt_test_step) { QTest ::qWait(qt_test_step); }; if (!((((expr))))) { if (!(((((expr )))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !(((((expr))))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if ((((expr )))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("(((expr)))")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 165); return;} while (false); } }; do { if (!QTest::qVerify (static_cast<bool>((expr)), "(expr)", "", "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 165)) return;} while (false); } while (false) QTRY_VERIFY_WITH_TIMEOUT((expr), 5000)do { const int qt_test_step = 5000 < 350 ? 5000 / 7 + 1 : 50 ; const int qt_test_timeoutValue = 5000; if (!((((expr))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !((((expr)))); qt_test_i += qt_test_step) { QTest ::qWait(qt_test_step); }; if (!((((expr))))) { if (!(((((expr )))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !(((((expr))))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if ((((expr )))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("(((expr)))")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 165); return;} while (false); } }; do { if (!QTest::qVerify (static_cast<bool>((expr)), "(expr)", "", "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 165)) return;} while (false); } while (false) | |||
166 | ||||
167 | // Will try to wait for the expression to become true while allowing event processing | |||
168 | #define QTRY_VERIFY2_WITH_TIMEOUT(expr, messageExpression, timeout)do { const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; const int qt_test_timeoutValue = timeout; if (!(((expr )))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !(((expr))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if (!(((expr) ))) { if (!((((expr))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !((((expr)))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step ); }; if (((expr))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("((expr))")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 168); return;} while (false); } }; do { if (expr) { if (!QTest ::qVerify(true, "expr", (messageExpression), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 168)) return; } else { if (!QTest::qVerify(false, "expr", ( messageExpression), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 168)) return; }} while (false); } while (false) \ | |||
169 | do { \ | |||
170 | QTRY_IMPL((expr), timeout)const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; const int qt_test_timeoutValue = timeout; if (!(((expr)) )) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !(((expr))); qt_test_i += qt_test_step ) { QTest::qWait(qt_test_step); }; if (!(((expr)))) { if (!(( ((expr))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !((((expr)))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if (((expr ))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("((expr))")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 170); return;} while (false); } };\ | |||
171 | QVERIFY2(expr, messageExpression)do { if (expr) { if (!QTest::qVerify(true, "expr", (messageExpression ), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 171)) return; } else { if (!QTest::qVerify(false, "expr", (messageExpression ), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 171)) return; }} while (false); \ | |||
172 | } while (false) | |||
173 | ||||
174 | #define QTRY_VERIFY2(expr, messageExpression)do { const int qt_test_step = 5000 < 350 ? 5000 / 7 + 1 : 50 ; const int qt_test_timeoutValue = 5000; if (!((((expr))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !((((expr)))); qt_test_i += qt_test_step) { QTest ::qWait(qt_test_step); }; if (!((((expr))))) { if (!(((((expr )))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !(((((expr))))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if ((((expr )))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("(((expr)))")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 174); return;} while (false); } }; do { if ((expr)) { if (! QTest::qVerify(true, "(expr)", ((messageExpression)), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 174)) return; } else { if (!QTest::qVerify(false, "(expr)", ((messageExpression)), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 174)) return; }} while (false); } while (false) QTRY_VERIFY2_WITH_TIMEOUT((expr), (messageExpression), 5000)do { const int qt_test_step = 5000 < 350 ? 5000 / 7 + 1 : 50 ; const int qt_test_timeoutValue = 5000; if (!((((expr))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !((((expr)))); qt_test_i += qt_test_step) { QTest ::qWait(qt_test_step); }; if (!((((expr))))) { if (!(((((expr )))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !(((((expr))))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step); }; if ((((expr )))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("(((expr)))")).arg(qt_test_timeoutValue ).arg(qt_test_timeoutValue + qt_test_i); do { QTest::qFail(QtPrivate ::asString(msg).toLocal8Bit().constData(), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 174); return;} while (false); } }; do { if ((expr)) { if (! QTest::qVerify(true, "(expr)", ((messageExpression)), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 174)) return; } else { if (!QTest::qVerify(false, "(expr)", ((messageExpression)), "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 174)) return; }} while (false); } while (false) | |||
175 | ||||
176 | // Will try to wait for the comparison to become successful while allowing event processing | |||
177 | #define QTRY_COMPARE_WITH_TIMEOUT(expr, expected, timeout)do { const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; const int qt_test_timeoutValue = timeout; if (!((((expr ) == (expected))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !((((expr) == (expected)))); qt_test_i += qt_test_step) { QTest::qWait( qt_test_step); }; if (!((((expr) == (expected))))) { if (!((( ((expr) == (expected)))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !(((((expr) == (expected))))); qt_test_i += qt_test_step) { QTest ::qWait(qt_test_step); }; if ((((expr) == (expected)))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("(((expr) == (expected)))" )).arg(qt_test_timeoutValue).arg(qt_test_timeoutValue + qt_test_i ); do { QTest::qFail(QtPrivate::asString(msg).toLocal8Bit().constData (), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 177); return ;} while (false); } }; do { if (!QTest::qCompare((expr), expected , "(expr)", "expected", "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 177)) return;} while (false); } while (false) \ | |||
178 | do { \ | |||
179 | QTRY_IMPL(((expr) == (expected)), timeout)const int qt_test_step = timeout < 350 ? timeout / 7 + 1 : 50; const int qt_test_timeoutValue = timeout; if (!((((expr) == (expected))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !((((expr) == (expected)))); qt_test_i += qt_test_step) { QTest::qWait( qt_test_step); }; if (!((((expr) == (expected))))) { if (!((( ((expr) == (expected)))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < (2 * qt_test_timeoutValue) && !(((((expr) == (expected))))); qt_test_i += qt_test_step) { QTest ::qWait(qt_test_step); }; if ((((expr) == (expected)))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("(((expr) == (expected)))" )).arg(qt_test_timeoutValue).arg(qt_test_timeoutValue + qt_test_i ); do { QTest::qFail(QtPrivate::asString(msg).toLocal8Bit().constData (), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 179); return ;} while (false); } };\ | |||
180 | QCOMPARE((expr), expected)do { if (!QTest::qCompare((expr), expected, "(expr)", "expected" , "/usr/lib64/qt5/include/QtTest/qtestcase.h", 180)) return;} while (false); \ | |||
181 | } while (false) | |||
182 | ||||
183 | #define QTRY_COMPARE(expr, expected)do { const int qt_test_step = 5000 < 350 ? 5000 / 7 + 1 : 50 ; const int qt_test_timeoutValue = 5000; if (!(((((expr)) == ( expected))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !(((((expr)) == (expected )))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step) ; }; if (!(((((expr)) == (expected))))) { if (!((((((expr)) == (expected)))))) { QTest::qWait(0); } int qt_test_i = 0; for ( ; qt_test_i < (2 * qt_test_timeoutValue) && !((((( (expr)) == (expected))))); qt_test_i += qt_test_step) { QTest ::qWait(qt_test_step); }; if (((((expr)) == (expected)))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("((((expr)) == (expected)))" )).arg(qt_test_timeoutValue).arg(qt_test_timeoutValue + qt_test_i ); do { QTest::qFail(QtPrivate::asString(msg).toLocal8Bit().constData (), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 183); return ;} while (false); } }; do { if (!QTest::qCompare(((expr)), expected , "((expr))", "expected", "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 183)) return;} while (false); } while (false) QTRY_COMPARE_WITH_TIMEOUT((expr), expected, 5000)do { const int qt_test_step = 5000 < 350 ? 5000 / 7 + 1 : 50 ; const int qt_test_timeoutValue = 5000; if (!(((((expr)) == ( expected))))) { QTest::qWait(0); } int qt_test_i = 0; for (; qt_test_i < qt_test_timeoutValue && !(((((expr)) == (expected )))); qt_test_i += qt_test_step) { QTest::qWait(qt_test_step) ; }; if (!(((((expr)) == (expected))))) { if (!((((((expr)) == (expected)))))) { QTest::qWait(0); } int qt_test_i = 0; for ( ; qt_test_i < (2 * qt_test_timeoutValue) && !((((( (expr)) == (expected))))); qt_test_i += qt_test_step) { QTest ::qWait(qt_test_step); }; if (((((expr)) == (expected)))) { QString msg = QString::fromUtf8("QTestLib: This test case check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 ms would have been sufficient this time." ); msg = msg.arg(QString::fromUtf8("((((expr)) == (expected)))" )).arg(qt_test_timeoutValue).arg(qt_test_timeoutValue + qt_test_i ); do { QTest::qFail(QtPrivate::asString(msg).toLocal8Bit().constData (), "/usr/lib64/qt5/include/QtTest/qtestcase.h", 183); return ;} while (false); } }; do { if (!QTest::qCompare(((expr)), expected , "((expr))", "expected", "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 183)) return;} while (false); } while (false) | |||
184 | ||||
185 | #define QSKIP_INTERNAL(statement)do { QTest::qSkip(statement, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 185); return;} while (false) \ | |||
186 | do {\ | |||
187 | QTest::qSkip(statement, __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__187);\ | |||
188 | return;\ | |||
189 | } while (false) | |||
190 | ||||
191 | #ifdef Q_COMPILER_VARIADIC_MACROS | |||
192 | ||||
193 | #define QSKIP(statement, ...)do { QTest::qSkip(statement, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 193); return;} while (false) QSKIP_INTERNAL(statement)do { QTest::qSkip(statement, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 193); return;} while (false) | |||
194 | ||||
195 | #else | |||
196 | ||||
197 | #define QSKIP(statement)do { QTest::qSkip(statement, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 197); return;} while (false) QSKIP_INTERNAL(statement)do { QTest::qSkip(statement, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 197); return;} while (false) | |||
198 | ||||
199 | #endif | |||
200 | ||||
201 | #define QEXPECT_FAIL(dataIndex, comment, mode)do { if (!QTest::qExpectFail(dataIndex, comment, QTest::mode, "/usr/lib64/qt5/include/QtTest/qtestcase.h", 201)) return;} while (false)\ | |||
202 | do {\ | |||
203 | if (!QTest::qExpectFail(dataIndex, comment, QTest::mode, __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__203))\ | |||
204 | return;\ | |||
205 | } while (false) | |||
206 | ||||
207 | #define QFETCH(Type, name)Type name = *static_cast<Type *>(QTest::qData("name", :: qMetaTypeId<typename std::remove_cv<Type >::type> ()))\ | |||
208 | Type name = *static_cast<Type *>(QTest::qData(#name, ::qMetaTypeId<typename std::remove_cv<Type >::type>())) | |||
209 | ||||
210 | #define QFETCH_GLOBAL(Type, name)Type name = *static_cast<Type *>(QTest::qGlobalData("name" , ::qMetaTypeId<typename std::remove_cv<Type >::type >()))\ | |||
211 | Type name = *static_cast<Type *>(QTest::qGlobalData(#name, ::qMetaTypeId<typename std::remove_cv<Type >::type>())) | |||
212 | ||||
213 | #define QTEST(actual, testElement)do { if (!QTest::qTest(actual, testElement, "actual", "testElement" , "/usr/lib64/qt5/include/QtTest/qtestcase.h", 213)) return;} while (false)\ | |||
214 | do {\ | |||
215 | if (!QTest::qTest(actual, testElement, #actual, #testElement, __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__215))\ | |||
216 | return;\ | |||
217 | } while (false) | |||
218 | ||||
219 | #define QWARN(msg)QTest::qWarn(msg, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 219)\ | |||
220 | QTest::qWarn(msg, __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__220) | |||
221 | ||||
222 | #ifdef QT_TESTCASE_BUILDDIR"/mnt/devel/GIT/6.x/build.scan" | |||
223 | # define QFINDTESTDATA(basepath)QTest::qFindTestData(basepath, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 223, "/mnt/devel/GIT/6.x/build.scan")\ | |||
224 | QTest::qFindTestData(basepath, __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__224, QT_TESTCASE_BUILDDIR"/mnt/devel/GIT/6.x/build.scan") | |||
225 | #else | |||
226 | # define QFINDTESTDATA(basepath)QTest::qFindTestData(basepath, "/usr/lib64/qt5/include/QtTest/qtestcase.h" , 226, "/mnt/devel/GIT/6.x/build.scan")\ | |||
227 | QTest::qFindTestData(basepath, __FILE__"/usr/lib64/qt5/include/QtTest/qtestcase.h", __LINE__227) | |||
228 | #endif | |||
229 | ||||
230 | # define QEXTRACTTESTDATA(resourcePath)QTest::qExtractTestData(resourcePath) \ | |||
231 | QTest::qExtractTestData(resourcePath) | |||
232 | ||||
233 | class QObject; | |||
234 | class QTestData; | |||
235 | ||||
236 | #define QTEST_COMPARE_DECL(KLASS)\ | |||
237 | template<> Q_TESTLIB_EXPORT__attribute__((visibility("default"))) char *toString<KLASS >(const KLASS &); | |||
238 | ||||
239 | namespace QTest | |||
240 | { | |||
241 | namespace Internal { | |||
242 | ||||
243 | template<typename T> // Output registered enums | |||
244 | inline typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, char*>::type toString(T e) | |||
245 | { | |||
246 | QMetaEnum me = QMetaEnum::fromType<T>(); | |||
247 | return qstrdup(me.valueToKey(int(e))); // int cast is necessary to support enum classes | |||
248 | } | |||
249 | ||||
250 | template <typename T> // Fallback | |||
251 | inline typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value, char*>::type toString(const T &) | |||
252 | { | |||
253 | return nullptr; | |||
254 | } | |||
255 | ||||
256 | template<typename F> // Output QFlags of registered enumerations | |||
257 | inline typename std::enable_if<QtPrivate::IsQEnumHelper<F>::Value, char*>::type toString(QFlags<F> f) | |||
258 | { | |||
259 | const QMetaEnum me = QMetaEnum::fromType<F>(); | |||
260 | return qstrdup(me.valueToKeys(int(f)).constData()); | |||
261 | } | |||
262 | ||||
263 | template <typename F> // Fallback: Output hex value | |||
264 | inline typename std::enable_if<!QtPrivate::IsQEnumHelper<F>::Value, char*>::type toString(QFlags<F> f) | |||
265 | { | |||
266 | const size_t space = 3 + 2 * sizeof(unsigned); // 2 for 0x, two hex digits per byte, 1 for '\0' | |||
267 | char *msg = new char[space]; | |||
268 | qsnprintf(msg, space, "0x%x", unsigned(f)); | |||
269 | return msg; | |||
270 | } | |||
271 | ||||
272 | } // namespace Internal | |||
273 | ||||
274 | template<typename T> | |||
275 | inline char *toString(const T &t) | |||
276 | { | |||
277 | return Internal::toString(t); | |||
278 | } | |||
279 | ||||
280 | template <typename T1, typename T2> | |||
281 | inline char *toString(const QPair<T1, T2> &pair); | |||
282 | ||||
283 | template <typename T1, typename T2> | |||
284 | inline char *toString(const std::pair<T1, T2> &pair); | |||
285 | ||||
286 | template <class... Types> | |||
287 | inline char *toString(const std::tuple<Types...> &tuple); | |||
288 | ||||
289 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) char *toHexRepresentation(const char *ba, int length); | |||
290 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) char *toPrettyCString(const char *unicode, int length); | |||
291 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) char *toPrettyUnicode(QStringView string); | |||
292 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) char *toString(const char *); | |||
293 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) char *toString(const void *); | |||
294 | ||||
295 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void qInit(QObject *testObject, int argc = 0, char **argv = nullptr); | |||
296 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) int qRun(); | |||
297 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void qCleanup(); | |||
298 | ||||
299 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) int qExec(QObject *testObject, int argc = 0, char **argv = nullptr); | |||
300 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) int qExec(QObject *testObject, const QStringList &arguments); | |||
301 | ||||
302 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void setMainSourcePath(const char *file, const char *builddir = nullptr); | |||
303 | ||||
304 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) bool qVerify(bool statement, const char *statementStr, const char *description, | |||
305 | const char *file, int line); | |||
306 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void qFail(const char *statementStr, const char *file, int line); | |||
307 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void qSkip(const char *message, const char *file, int line); | |||
308 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) bool qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode, | |||
309 | const char *file, int line); | |||
310 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void qWarn(const char *message, const char *file = nullptr, int line = 0); | |||
311 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void ignoreMessage(QtMsgType type, const char *message); | |||
312 | #if QT_CONFIG(regularexpression)(1/1 == 1) | |||
313 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern); | |||
314 | #endif | |||
315 | ||||
316 | #if QT_CONFIG(temporaryfile)(1/1 == 1) | |||
317 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) QSharedPointer<QTemporaryDir> qExtractTestData(const QString &dirName); | |||
318 | #endif | |||
319 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) QString qFindTestData(const char* basepath, const char* file = nullptr, int line = 0, const char* builddir = nullptr); | |||
320 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) QString qFindTestData(const QString& basepath, const char* file = nullptr, int line = 0, const char* builddir = nullptr); | |||
321 | ||||
322 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void *qData(const char *tagName, int typeId); | |||
323 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void *qGlobalData(const char *tagName, int typeId); | |||
324 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void *qElementData(const char *elementName, int metaTypeId); | |||
325 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) QObject *testObject(); | |||
326 | ||||
327 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) const char *currentAppName(); | |||
328 | ||||
329 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) const char *currentTestFunction(); | |||
330 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) const char *currentDataTag(); | |||
331 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) bool currentTestFailed(); | |||
332 | ||||
333 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) Qt::Key asciiToKey(char ascii); | |||
334 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) char keyToAscii(Qt::Key key); | |||
335 | ||||
336 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) bool compare_helper(bool success, const char *failureMsg, | |||
337 | char *val1, char *val2, | |||
338 | const char *actual, const char *expected, | |||
339 | const char *file, int line); | |||
340 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void qSleep(int ms); | |||
341 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) void addColumnInternal(int id, const char *name); | |||
342 | ||||
343 | template <typename T> | |||
344 | inline void addColumn(const char *name, T * = nullptr) | |||
345 | { | |||
346 | typedef std::is_same<T, const char*> QIsSameTConstChar; | |||
347 | Q_STATIC_ASSERT_X(!QIsSameTConstChar::value, "const char* is not allowed as a test data format.")static_assert(bool(!QIsSameTConstChar::value), "const char* is not allowed as a test data format." ); | |||
348 | addColumnInternal(qMetaTypeId<T>(), name); | |||
349 | } | |||
350 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) QTestData &newRow(const char *dataTag); | |||
351 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) QTestData &addRow(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2)__attribute__((format(printf, (1), (2)))); | |||
352 | ||||
353 | #if QT_VERSION((5<<16)|(12<<8)|(2)) < QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)) | |||
354 | // kept after adding implementation of <T1, T2> out of paranoia: | |||
355 | template <typename T> | |||
356 | inline bool qCompare(T const &t1, T const &t2, const char *actual, const char *expected, | |||
357 | const char *file, int line) | |||
358 | { | |||
359 | return compare_helper(t1 == t2, "Compared values are not the same", | |||
| ||||
360 | toString(t1), toString(t2), actual, expected, file, line); | |||
360 | toString(t1), toString(t2), actual, expected, file, line); | |||
361 | } | |||
362 | #endif | |||
363 | ||||
364 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) bool qCompare(float const &t1, float const &t2, | |||
365 | const char *actual, const char *expected, const char *file, int line); | |||
366 | ||||
367 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) bool qCompare(double const &t1, double const &t2, | |||
368 | const char *actual, const char *expected, const char *file, int line); | |||
369 | ||||
370 | inline bool compare_ptr_helper(const volatile void *t1, const volatile void *t2, const char *actual, | |||
371 | const char *expected, const char *file, int line) | |||
372 | { | |||
373 | return compare_helper(t1 == t2, "Compared pointers are not the same", | |||
374 | toString(t1), toString(t2), actual, expected, file, line); | |||
375 | } | |||
376 | ||||
377 | inline bool compare_ptr_helper(const volatile void *t1, std::nullptr_t, const char *actual, | |||
378 | const char *expected, const char *file, int line) | |||
379 | { | |||
380 | return compare_helper(t1 == nullptr, "Compared pointers are not the same", | |||
381 | toString(t1), toString(nullptr), actual, expected, file, line); | |||
382 | } | |||
383 | ||||
384 | inline bool compare_ptr_helper(std::nullptr_t, const volatile void *t2, const char *actual, | |||
385 | const char *expected, const char *file, int line) | |||
386 | { | |||
387 | return compare_helper(nullptr == t2, "Compared pointers are not the same", | |||
388 | toString(nullptr), toString(t2), actual, expected, file, line); | |||
389 | } | |||
390 | ||||
391 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) bool compare_string_helper(const char *t1, const char *t2, const char *actual, | |||
392 | const char *expected, const char *file, int line); | |||
393 | ||||
394 | Q_TESTLIB_EXPORT__attribute__((visibility("default"))) char *formatString(const char *prefix, const char *suffix, size_t numArguments, ...); | |||
395 | ||||
396 | #ifndef Q_QDOC | |||
397 | QTEST_COMPARE_DECL(short) | |||
398 | QTEST_COMPARE_DECL(ushort) | |||
399 | QTEST_COMPARE_DECL(int) | |||
400 | QTEST_COMPARE_DECL(uint) | |||
401 | QTEST_COMPARE_DECL(long) | |||
402 | QTEST_COMPARE_DECL(ulong) | |||
403 | QTEST_COMPARE_DECL(qint64) | |||
404 | QTEST_COMPARE_DECL(quint64) | |||
405 | ||||
406 | QTEST_COMPARE_DECL(float) | |||
407 | QTEST_COMPARE_DECL(double) | |||
408 | QTEST_COMPARE_DECL(char) | |||
409 | QTEST_COMPARE_DECL(signed char) | |||
410 | QTEST_COMPARE_DECL(unsigned char) | |||
411 | QTEST_COMPARE_DECL(bool) | |||
412 | #endif | |||
413 | ||||
414 | template <typename T1, typename T2> | |||
415 | inline bool qCompare(const T1 &t1, const T2 &t2, const char *actual, const char *expected, | |||
416 | const char *file, int line) | |||
417 | { | |||
418 | return compare_helper(t1 == t2, "Compared values are not the same", | |||
419 | toString(t1), toString(t2), actual, expected, file, line); | |||
420 | } | |||
421 | ||||
422 | inline bool qCompare(double const &t1, float const &t2, const char *actual, | |||
423 | const char *expected, const char *file, int line) | |||
424 | { | |||
425 | return qCompare(qreal(t1), qreal(t2), actual, expected, file, line); | |||
426 | } | |||
427 | ||||
428 | inline bool qCompare(float const &t1, double const &t2, const char *actual, | |||
429 | const char *expected, const char *file, int line) | |||
430 | { | |||
431 | return qCompare(qreal(t1), qreal(t2), actual, expected, file, line); | |||
432 | } | |||
433 | ||||
434 | template <typename T> | |||
435 | inline bool qCompare(const T *t1, const T *t2, const char *actual, const char *expected, | |||
436 | const char *file, int line) | |||
437 | { | |||
438 | return compare_ptr_helper(t1, t2, actual, expected, file, line); | |||
439 | } | |||
440 | template <typename T> | |||
441 | inline bool qCompare(T *t1, T *t2, const char *actual, const char *expected, | |||
442 | const char *file, int line) | |||
443 | { | |||
444 | return compare_ptr_helper(t1, t2, actual, expected, file, line); | |||
445 | } | |||
446 | ||||
447 | template <typename T> | |||
448 | inline bool qCompare(T *t1, std::nullptr_t, const char *actual, const char *expected, | |||
449 | const char *file, int line) | |||
450 | { | |||
451 | return compare_ptr_helper(t1, nullptr, actual, expected, file, line); | |||
452 | } | |||
453 | template <typename T> | |||
454 | inline bool qCompare(std::nullptr_t, T *t2, const char *actual, const char *expected, | |||
455 | const char *file, int line) | |||
456 | { | |||
457 | return compare_ptr_helper(nullptr, t2, actual, expected, file, line); | |||
458 | } | |||
459 | ||||
460 | template <typename T1, typename T2> | |||
461 | inline bool qCompare(const T1 *t1, const T2 *t2, const char *actual, const char *expected, | |||
462 | const char *file, int line) | |||
463 | { | |||
464 | return compare_ptr_helper(t1, static_cast<const T1 *>(t2), actual, expected, file, line); | |||
465 | } | |||
466 | template <typename T1, typename T2> | |||
467 | inline bool qCompare(T1 *t1, T2 *t2, const char *actual, const char *expected, | |||
468 | const char *file, int line) | |||
469 | { | |||
470 | return compare_ptr_helper(const_cast<const T1 *>(t1), | |||
471 | static_cast<const T1 *>(const_cast<const T2 *>(t2)), actual, expected, file, line); | |||
472 | } | |||
473 | inline bool qCompare(const char *t1, const char *t2, const char *actual, | |||
474 | const char *expected, const char *file, int line) | |||
475 | { | |||
476 | return compare_string_helper(t1, t2, actual, expected, file, line); | |||
477 | } | |||
478 | inline bool qCompare(char *t1, char *t2, const char *actual, const char *expected, | |||
479 | const char *file, int line) | |||
480 | { | |||
481 | return compare_string_helper(t1, t2, actual, expected, file, line); | |||
482 | } | |||
483 | ||||
484 | /* The next two overloads are for MSVC that shows problems with implicit | |||
485 | conversions | |||
486 | */ | |||
487 | inline bool qCompare(char *t1, const char *t2, const char *actual, | |||
488 | const char *expected, const char *file, int line) | |||
489 | { | |||
490 | return compare_string_helper(t1, t2, actual, expected, file, line); | |||
491 | } | |||
492 | inline bool qCompare(const char *t1, char *t2, const char *actual, | |||
493 | const char *expected, const char *file, int line) | |||
494 | { | |||
495 | return compare_string_helper(t1, t2, actual, expected, file, line); | |||
496 | } | |||
497 | ||||
498 | template <class T> | |||
499 | inline bool qTest(const T& actual, const char *elementName, const char *actualStr, | |||
500 | const char *expected, const char *file, int line) | |||
501 | { | |||
502 | return qCompare(actual, *static_cast<const T *>(QTest::qElementData(elementName, | |||
503 | qMetaTypeId<T>())), actualStr, expected, file, line); | |||
504 | } | |||
505 | } | |||
506 | ||||
507 | #undef QTEST_COMPARE_DECL | |||
508 | ||||
509 | QT_END_NAMESPACE | |||
510 | ||||
511 | #endif |
File: | mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp |
Warning: | line 89, column 25 Potential leak of memory pointed to by 'e1' |
Press '?' - to see keyboard shortcuts
- - -Keyboard shortcuts:
-1 | /* ============================================================ | |||
2 | * | |||
3 | * This file is a part of digiKam project | |||
4 | * https://www.digikam.org | |||
5 | * | |||
6 | * Date : 2011-03-22 | |||
7 | * Description : a MediaWiki C++ interface | |||
8 | * | |||
9 | * Copyright (C) 2011-2019 by Gilles Caulier <caulier dot gilles at gmail dot com> | |||
10 | * Copyright (C) 2011 by Alexandre Mendes <alex dot mendes1988 at gmail dot com> | |||
11 | * Copyright (C) 2011 by Hormiere Guillaume <hormiere dot guillaume at gmail dot com> | |||
12 | * Copyright (C) 2011 by Manuel Campomanes <campomanes dot manuel at gmail dot com> | |||
13 | * | |||
14 | * This program is free software; you can redistribute it | |||
15 | * and/or modify it under the terms of the GNU General | |||
16 | * Public License as published by the Free Software Foundation; | |||
17 | * either version 2, or (at your option) any later version. | |||
18 | * | |||
19 | * This program 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 | * ============================================================ */ | |||
25 | ||||
26 | #include "mainwindow.h" | |||
27 | #include "ui_mainwindow.h" | |||
28 | ||||
29 | // Qt includes | |||
30 | ||||
31 | #include <QFile> | |||
32 | #include <QFileDialog> | |||
33 | ||||
34 | MainWindow::MainWindow(QWidget *parent) | |||
35 | : QMainWindow(parent), | |||
36 | ui(new Ui::MainWindow), | |||
37 | MediaWiki(QUrl(QLatin1String("https://test.wikipedia.org/w/api.php"))) | |||
38 | { | |||
39 | ui->setupUi(this); | |||
40 | init(); | |||
41 | } | |||
42 | ||||
43 | MainWindow::~MainWindow() | |||
44 | { | |||
45 | delete ui; | |||
46 | } | |||
47 | ||||
48 | void MainWindow::init() | |||
49 | { | |||
50 | this->ui->comboBox->addItem(QLatin1String("Own work, multi-license with CC-BY-SA-3.0 and GFDL"), QLatin1String("{{self|cc-by-sa-3.0|GFDL|migration=redundant}}")); | |||
51 | this->ui->comboBox->addItem(QLatin1String("Own work, multi-license with CC-BY-SA-3.0 and older"), QLatin1String("{{self|cc-by-sa-3.0,2.5,2.0,1.0}}")); | |||
52 | this->ui->comboBox->addItem(QLatin1String("Creative Commons Attribution-Share Alike 3.0"), QLatin1String("{{self|cc-by-sa-3.0}}")); | |||
53 | this->ui->comboBox->addItem(QLatin1String("Own work, Creative Commons Attribution 3.0"), QLatin1String("{{self|cc-by-3.0}}")); | |||
54 | this->ui->comboBox->addItem(QLatin1String("Own work, release into public domain under the CC-Zero license"), QLatin1String("{{self|cc-zero}}")); | |||
55 | this->ui->comboBox->addItem(QLatin1String("Author died more than 100 years ago"), QLatin1String("{{PD-old}}")); | |||
56 | this->ui->comboBox->addItem(QLatin1String("Photo of a two-dimensional work whose author died more than 100 years ago"), QLatin1String("{{PD-art}}")); | |||
57 | this->ui->comboBox->addItem(QLatin1String("First published in the United States before 1923"), QLatin1String("{{PD-US}}")); | |||
58 | this->ui->comboBox->addItem(QLatin1String("Work of a U.S. government agency"), QLatin1String("{{PD-USGov}}")); | |||
59 | this->ui->comboBox->addItem(QLatin1String("Simple typefaces, individual words or geometric shapes"), QLatin1String("{{PD-text}}")); | |||
60 | this->ui->comboBox->addItem(QLatin1String("Logos with only simple typefaces, individual words or geometric shapes"), QLatin1String("{{PD-textlogo}}")); | |||
61 | } | |||
62 | ||||
63 | void MainWindow::on_pushButton_clicked() | |||
64 | { | |||
65 | this->ui->progressBar->setValue(0); | |||
66 | Login* const login = new Login(MediaWiki, this->ui->mLoginEdit->text(), this->ui->mMdpEdit->text()); | |||
67 | ||||
68 | connect(login, SIGNAL(result(KJob*))qFlagLocation("2""result(KJob*)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "68"), | |||
69 | this, SLOT(loginHandle(KJob*))qFlagLocation("1""loginHandle(KJob*)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "69")); | |||
70 | ||||
71 | login->start(); | |||
72 | } | |||
73 | ||||
74 | void MainWindow::loginHandle(KJob* login) | |||
75 | { | |||
76 | if (login->error() != 0) | |||
| ||||
77 | { | |||
78 | QMessageBox popup; | |||
79 | popup.setText(QLatin1String("Wrong authentication.")); | |||
80 | popup.exec(); | |||
81 | } | |||
82 | else | |||
83 | { | |||
84 | Upload* const e1 = new Upload( MediaWiki ); | |||
85 | QFile* const file = new QFile(this->ui->lineEdit->text()); | |||
86 | ||||
87 | if (!file->open(QIODevice::ReadOnly)) | |||
88 | { | |||
89 | QMessageBox popup; | |||
| ||||
90 | popup.setText(QString::fromLatin1("Cannot open file %1.").arg(this->ui->lineEdit->text())); | |||
91 | popup.exec(); | |||
92 | return; | |||
93 | } | |||
94 | ||||
95 | e1->setFile(file); | |||
96 | e1->setFilename(this->ui->lineEdit_2->text()); | |||
97 | ||||
98 | QString text = QLatin1String("== {{int:filedesc}} == \n{{Information |Description="); | |||
99 | text.append(this->ui->descriptionEdit->text()); | |||
100 | text.append(QLatin1String("\n|Source=")).append(this->ui->sourceEdit->text()); | |||
101 | text.append(QLatin1String("\n|Date=")).append(this->ui->dateEdit->text()); | |||
102 | text.append(QLatin1String("\n|Author=")).append(this->ui->authorEdit->text()); | |||
103 | text.append(QLatin1String("\n|Permission=")).append(this->ui->permissionEdit->text()); | |||
104 | text.append(QLatin1String("\n|other_versions=")).append(this->ui->versionsEdit->text()); | |||
105 | text.append(QLatin1String("\n}}\n== {{int:license}} ==\n")); | |||
106 | text.append(this->ui->comboBox->itemData(this->ui->comboBox->currentIndex()).toString()); | |||
107 | ||||
108 | e1->setText(text); | |||
109 | ||||
110 | connect(e1, SIGNAL(result(KJob*))qFlagLocation("2""result(KJob*)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "110"), | |||
111 | this, SLOT(uploadHandle(KJob*))qFlagLocation("1""uploadHandle(KJob*)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "111")); | |||
112 | ||||
113 | connect(e1,SIGNAL(processedSize(KJob*,qulonglong))qFlagLocation("2""processedSize(KJob*,qulonglong)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "113"), | |||
114 | this, SLOT(processedUploadSize(KJob*,qulonglong))qFlagLocation("1""processedUploadSize(KJob*,qulonglong)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "114")); | |||
115 | ||||
116 | connect(e1,SIGNAL(totalSize(KJob*,qulonglong))qFlagLocation("2""totalSize(KJob*,qulonglong)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "116"), | |||
117 | this,SLOT(TotalUploadSize(KJob*,qulonglong))qFlagLocation("1""TotalUploadSize(KJob*,qulonglong)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "117")); | |||
118 | ||||
119 | e1->start(); | |||
120 | } | |||
121 | } | |||
122 | ||||
123 | void MainWindow::uploadHandle(KJob* job) | |||
124 | { | |||
125 | disconnect(this, SIGNAL(result(KJob*))qFlagLocation("2""result(KJob*)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "125"), | |||
126 | this, SLOT(uploadHandle(KJob*))qFlagLocation("1""uploadHandle(KJob*)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "126")); | |||
127 | ||||
128 | disconnect(this, SIGNAL(processedSize(KJob*,qulonglong))qFlagLocation("2""processedSize(KJob*,qulonglong)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "128"), | |||
129 | this, SLOT(processedUploadSize(KJob*,qulonglong))qFlagLocation("1""processedUploadSize(KJob*,qulonglong)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "129")); | |||
130 | ||||
131 | disconnect(this, SIGNAL(totalSize(KJob*,qulonglong))qFlagLocation("2""totalSize(KJob*,qulonglong)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "131"), | |||
132 | this, SLOT(TotalUploadSize(KJob*,qulonglong))qFlagLocation("1""TotalUploadSize(KJob*,qulonglong)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/generic/webservices/mediawiki/tests/examples/uploadsample/mainwindow.cpp" ":" "132")); | |||
133 | ||||
134 | QString errorMessage; | |||
135 | ||||
136 | if (job->error() == 0) | |||
137 | { | |||
138 | errorMessage = QLatin1String("Image uploaded successfully."); | |||
139 | } | |||
140 | else | |||
141 | { | |||
142 | errorMessage = QLatin1String("Image upload failed."); | |||
143 | } | |||
144 | ||||
145 | QMessageBox popup; | |||
146 | popup.setText(errorMessage); | |||
147 | popup.exec(); | |||
148 | } | |||
149 | ||||
150 | void MainWindow::processedUploadSize(KJob* job, qulonglong size) | |||
151 | { | |||
152 | Q_UNUSED(job)(void)job; | |||
153 | this->ui->progressBar->setValue(size); | |||
154 | } | |||
155 | ||||
156 | void MainWindow::TotalUploadSize(KJob* job, qulonglong size) | |||
157 | { | |||
158 | Q_UNUSED(job)(void)job; | |||
159 | this->ui->progressBar->setMaximum(size); | |||
160 | } | |||
161 | ||||
162 | void MainWindow::on_parcourir_clicked() | |||
163 | { | |||
164 | QString fileName = QFileDialog::getOpenFileName(this, | |||
165 | QLatin1String("Open Image"), | |||
166 | QLatin1String("~"), | |||
167 | QLatin1String("Image Files (*.png *.jpg *.bmp *.jpeg *.gif)")); | |||
168 | ||||
169 | if (!fileName.isEmpty()) | |||
170 | { | |||
171 | QPixmap preview(fileName); | |||
172 | QSize size(preview.size()); | |||
173 | size.scale(400, 200, Qt::KeepAspectRatio); | |||
174 | preview = preview.scaled(size, Qt::KeepAspectRatio, Qt::FastTransformation); | |||
175 | ||||
176 | this->ui->previewLabel->setPixmap(preview); | |||
177 | this->ui->lineEdit->setText(fileName); | |||
178 | } | |||
179 | } | |||
180 | ||||
181 | void MainWindow::on_lineEdit_textChanged(const QString& text) | |||
182 | { | |||
183 | this->ui->pushButton->setEnabled(!text.isEmpty() && !text.isNull()); | |||
184 | } |
File: | usr/lib64/qt5/include/QtCore/qscopedpointer.h |
Warning: | line 60, column 9 Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete' |
Press '?' to see keyboard shortcuts
-Keyboard shortcuts:
1 | /* ============================================================ | |||
2 | * | |||
3 | * This file is a part of digiKam project | |||
4 | * https://www.digikam.org | |||
5 | * | |||
6 | * Date : 2005-05-25 | |||
7 | * Description : Oil Painting threaded image filter. | |||
8 | * | |||
9 | * Copyright (C) 2005-2019 by Gilles Caulier <caulier dot gilles at gmail dot com> | |||
10 | * Copyright (C) 2006-2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> | |||
11 | * Copyright (C) 2010 by Martin Klapetek <martin dot klapetek at gmail dot com> | |||
12 | * | |||
13 | * Original OilPaint algorithm copyrighted 2004 by | |||
14 | * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot com>. | |||
15 | * | |||
16 | * This program is free software; you can redistribute it | |||
17 | * and/or modify it under the terms of the GNU General | |||
18 | * Public License as published by the Free Software Foundation; | |||
19 | * either version 2, or (at your option) | |||
20 | * any later version. | |||
21 | * | |||
22 | * This program is distributed in the hope that it will be useful, | |||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
25 | * GNU General Public License for more details. | |||
26 | * | |||
27 | * ============================================================ */ | |||
28 | ||||
29 | #include "oilpaintfilter.h" | |||
30 | ||||
31 | // C++ includes | |||
32 | ||||
33 | #include <cmath> | |||
34 | #include <cstdlib> | |||
35 | ||||
36 | // Qt includes | |||
37 | ||||
38 | #include <QtConcurrent> // krazy:exclude=includes | |||
39 | #include <QMutex> | |||
40 | ||||
41 | // KDE includes | |||
42 | ||||
43 | #include <klocalizedstring.h> | |||
44 | ||||
45 | // Local includes | |||
46 | ||||
47 | #include "dimg.h" | |||
48 | ||||
49 | namespace Digikam | |||
50 | { | |||
51 | ||||
52 | class Q_DECL_HIDDEN__attribute__((visibility("hidden"))) OilPaintFilter::Private | |||
53 | { | |||
54 | public: | |||
55 | ||||
56 | explicit Private() | |||
57 | : brushSize(1), | |||
58 | smoothness(30), | |||
59 | globalProgress(0) | |||
60 | { | |||
61 | } | |||
62 | ||||
63 | int brushSize; | |||
64 | int smoothness; | |||
65 | ||||
66 | int globalProgress; | |||
67 | ||||
68 | QMutex lock; | |||
69 | }; | |||
70 | ||||
71 | OilPaintFilter::OilPaintFilter(QObject* const parent) | |||
72 | : DImgThreadedFilter(parent), | |||
73 | d(new Private) | |||
74 | { | |||
75 | initFilter(); | |||
76 | } | |||
77 | ||||
78 | OilPaintFilter::OilPaintFilter(DImg* const orgImage, QObject* const parent, int brushSize, int smoothness) | |||
79 | : DImgThreadedFilter(orgImage, parent, QLatin1String("OilPaintFilter")), | |||
80 | d(new Private) | |||
81 | { | |||
82 | d->brushSize = brushSize; | |||
83 | d->smoothness = smoothness; | |||
84 | ||||
85 | initFilter(); | |||
86 | } | |||
87 | ||||
88 | OilPaintFilter::~OilPaintFilter() | |||
89 | { | |||
90 | cancelFilter(); | |||
91 | delete d; | |||
92 | } | |||
93 | ||||
94 | QString OilPaintFilter::DisplayableName() | |||
95 | { | |||
96 | return QString::fromUtf8(I18N_NOOP("Oil Painter Effect")"Oil Painter Effect"); | |||
97 | } | |||
98 | ||||
99 | /** Function to apply the OilPaintFilter effect. | |||
100 | * This method have been ported from Pieter Z. Voloshyn algorithm code. | |||
101 | * | |||
102 | * Theory: Using MostFrequentColor function we take the main color in | |||
103 | * a matrix and simply write at the original position. | |||
104 | */ | |||
105 | void OilPaintFilter::oilPaintImageMultithreaded(uint start, uint stop) | |||
106 | { | |||
107 | QScopedPointer<uchar> intensityCount(new uchar[d->smoothness + 1]); | |||
108 | QScopedPointer<uint> averageColorR(new uint[d->smoothness + 1]); | |||
109 | QScopedPointer<uint> averageColorG(new uint[d->smoothness + 1]); | |||
110 | QScopedPointer<uint> averageColorB(new uint[d->smoothness + 1]); | |||
| ||||
111 | ||||
112 | memset(intensityCount.data(), 0, sizeof(uchar)*(d->smoothness + 1)); | |||
113 | memset(averageColorR.data(), 0, sizeof(uint)*(d->smoothness + 1)); | |||
114 | memset(averageColorG.data(), 0, sizeof(uint)*(d->smoothness + 1)); | |||
115 | memset(averageColorB.data(), 0, sizeof(uint)*(d->smoothness + 1)); | |||
116 | ||||
117 | int oldProgress=0, progress=0; | |||
118 | DColor mostFrequentColor; | |||
119 | ||||
120 | mostFrequentColor.setSixteenBit(m_orgImage.sixteenBit()); | |||
121 | uchar* dest = m_destImage.bits(); | |||
122 | uchar* dptr = nullptr; | |||
123 | ||||
124 | for (uint h2 = start; runningFlag() && (h2 < stop); ++h2) | |||
125 | { | |||
126 | for (uint w2 = 0; runningFlag() && (w2 < m_orgImage.width()); ++w2) | |||
127 | { | |||
128 | mostFrequentColor = MostFrequentColor(m_orgImage, w2, h2, d->brushSize, d->smoothness, | |||
129 | intensityCount.data(), averageColorR.data(), averageColorG.data(), averageColorB.data()); | |||
130 | dptr = dest + w2 * m_orgImage.bytesDepth() + (m_orgImage.width() * h2 * m_orgImage.bytesDepth()); | |||
131 | mostFrequentColor.setPixel(dptr); | |||
132 | } | |||
133 | ||||
134 | progress = (int)( ( (double)h2 * (100.0 / QThreadPool::globalInstance()->maxThreadCount()) ) / (stop-start)); | |||
135 | ||||
136 | if ((progress % 5 == 0) && (progress > oldProgress)) | |||
137 | { | |||
138 | d->lock.lock(); | |||
139 | oldProgress = progress; | |||
140 | d->globalProgress += 5; | |||
141 | postProgress(d->globalProgress); | |||
142 | d->lock.unlock(); | |||
143 | } | |||
144 | } | |||
145 | } | |||
146 | ||||
147 | void OilPaintFilter::filterImage() | |||
148 | { | |||
149 | QList<int> vals = multithreadedSteps(m_orgImage.height()); | |||
150 | QList <QFuture<void> > tasks; | |||
151 | ||||
152 | for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j) | |||
153 | { | |||
154 | tasks.append(QtConcurrent::run(this, | |||
155 | &OilPaintFilter::oilPaintImageMultithreaded, | |||
156 | vals[j], | |||
157 | vals[j+1] | |||
158 | )); | |||
159 | } | |||
160 | ||||
161 | foreach (QFuture<void> t, tasks)for (auto _container_ = QtPrivate::qMakeForeachContainer(tasks ); _container_.control && _container_.i != _container_ .e; ++_container_.i, _container_.control ^= 1) for (QFuture< void> t = *_container_.i; _container_.control; _container_ .control = 0) | |||
162 | t.waitForFinished(); | |||
163 | } | |||
164 | ||||
165 | /** Function to determine the most frequent color in a matrix | |||
166 | * | |||
167 | * Bits => Bits array | |||
168 | * Width => Image width | |||
169 | * Height => Image height | |||
170 | * X => Position horizontal | |||
171 | * Y => Position vertical | |||
172 | * Radius => Is the radius of the matrix to be analyzed | |||
173 | * Intensity => Intensity to calculate | |||
174 | * | |||
175 | * Theory => This function creates a matrix with the analyzed pixel in | |||
176 | * the center of this matrix and find the most frequently color | |||
177 | */ | |||
178 | DColor OilPaintFilter::MostFrequentColor(DImg& src, int X, int Y, int Radius, int Intensity, | |||
179 | uchar* intensityCount, uint* averageColorR, uint* averageColorG, uint* averageColorB) | |||
180 | { | |||
181 | int i, w, h, I, Width, Height; | |||
182 | uint red, green, blue; | |||
183 | ||||
184 | uchar* dest = src.bits(); | |||
185 | int bytesDepth = src.bytesDepth(); | |||
186 | uchar* sptr = nullptr; | |||
187 | bool sixteenBit = src.sixteenBit(); | |||
188 | ||||
189 | DColor mostFrequentColor; | |||
190 | ||||
191 | double Scale = Intensity / (sixteenBit ? 65535.0 : 255.0); | |||
192 | Width = (int)src.width(); | |||
193 | Height = (int)src.height(); | |||
194 | ||||
195 | // Erase the array | |||
196 | memset(intensityCount, 0, (Intensity + 1) * sizeof(uchar)); | |||
197 | ||||
198 | for (w = X - Radius; w <= X + Radius; ++w) | |||
199 | { | |||
200 | for (h = Y - Radius; h <= Y + Radius; ++h) | |||
201 | { | |||
202 | // This condition helps to identify when a point doesn't exist | |||
203 | ||||
204 | if ((w >= 0) && (w < Width) && (h >= 0) && (h < Height)) | |||
205 | { | |||
206 | sptr = dest + w * bytesDepth + (Width * h * bytesDepth); | |||
207 | DColor color(sptr, sixteenBit); | |||
208 | red = (uint)color.red(); | |||
209 | green = (uint)color.green(); | |||
210 | blue = (uint)color.blue(); | |||
211 | ||||
212 | I = lround(GetIntensity(red, green, blue) * Scale); | |||
213 | intensityCount[I]++; | |||
214 | ||||
215 | if (intensityCount[I] == 1) | |||
216 | { | |||
217 | averageColorR[I] = red; | |||
218 | averageColorG[I] = green; | |||
219 | averageColorB[I] = blue; | |||
220 | } | |||
221 | else | |||
222 | { | |||
223 | averageColorR[I] += red; | |||
224 | averageColorG[I] += green; | |||
225 | averageColorB[I] += blue; | |||
226 | } | |||
227 | } | |||
228 | } | |||
229 | } | |||
230 | ||||
231 | I = 0; | |||
232 | int MaxInstance = 1; | |||
233 | ||||
234 | for (i = 0 ; i <= Intensity ; ++i) | |||
235 | { | |||
236 | if (intensityCount[i] > MaxInstance) | |||
237 | { | |||
238 | I = i; | |||
239 | MaxInstance = intensityCount[i]; | |||
240 | } | |||
241 | } | |||
242 | ||||
243 | // get Alpha channel value from original (unchanged) | |||
244 | mostFrequentColor = src.getPixelColor(X, Y); | |||
245 | ||||
246 | // Overwrite RGB values to destination. | |||
247 | mostFrequentColor.setRed(averageColorR[I] / MaxInstance); | |||
248 | mostFrequentColor.setGreen(averageColorG[I] / MaxInstance); | |||
249 | mostFrequentColor.setBlue(averageColorB[I] / MaxInstance); | |||
250 | ||||
251 | return mostFrequentColor; | |||
252 | } | |||
253 | ||||
254 | /** Function to calculate the color intensity and return the luminance (Y) | |||
255 | * component of YIQ color model. | |||
256 | */ | |||
257 | double OilPaintFilter::GetIntensity(uint Red, uint Green, uint Blue) | |||
258 | { | |||
259 | return Red * 0.3 + Green * 0.59 + Blue * 0.11; | |||
260 | } | |||
261 | ||||
262 | FilterAction OilPaintFilter::filterAction() | |||
263 | { | |||
264 | FilterAction action(FilterIdentifier(), CurrentVersion()); | |||
265 | action.setDisplayableName(DisplayableName()); | |||
266 | ||||
267 | action.addParameter(QLatin1String("brushSize"), d->brushSize); | |||
268 | action.addParameter(QLatin1String("smoothness"), d->smoothness); | |||
269 | ||||
270 | return action; | |||
271 | } | |||
272 | ||||
273 | void OilPaintFilter::readParameters(const Digikam::FilterAction& action) | |||
274 | { | |||
275 | d->brushSize = action.parameter(QLatin1String("brushSize")).toInt(); | |||
276 | d->smoothness = action.parameter(QLatin1String("smoothness")).toInt(); | |||
277 | } | |||
278 | ||||
279 | } // namespace Digikam |
1 | /**************************************************************************** | |||
2 | ** | |||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | |||
4 | ** Contact: https://www.qt.io/licensing/ | |||
5 | ** | |||
6 | ** This file is part of the QtCore module of the Qt Toolkit. | |||
7 | ** | |||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | |||
9 | ** Commercial License Usage | |||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | |||
11 | ** accordance with the commercial license agreement provided with the | |||
12 | ** Software or, alternatively, in accordance with the terms contained in | |||
13 | ** a written agreement between you and The Qt Company. For licensing terms | |||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | |||
15 | ** information use the contact form at https://www.qt.io/contact-us. | |||
16 | ** | |||
17 | ** GNU Lesser General Public License Usage | |||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | |||
19 | ** General Public License version 3 as published by the Free Software | |||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | |||
21 | ** packaging of this file. Please review the following information to | |||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | |||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | |||
24 | ** | |||
25 | ** GNU General Public License Usage | |||
26 | ** Alternatively, this file may be used under the terms of the GNU | |||
27 | ** General Public License version 2.0 or (at your option) the GNU General | |||
28 | ** Public license version 3 or any later version approved by the KDE Free | |||
29 | ** Qt Foundation. The licenses are as published by the Free Software | |||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | |||
31 | ** included in the packaging of this file. Please review the following | |||
32 | ** information to ensure the GNU General Public License requirements will | |||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | |||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | |||
35 | ** | |||
36 | ** $QT_END_LICENSE$ | |||
37 | ** | |||
38 | ****************************************************************************/ | |||
39 | ||||
40 | #ifndef QSCOPEDPOINTER_H | |||
41 | #define QSCOPEDPOINTER_H | |||
42 | ||||
43 | #include <QtCore/qglobal.h> | |||
44 | ||||
45 | #include <stdlib.h> | |||
46 | ||||
47 | QT_BEGIN_NAMESPACE | |||
48 | ||||
49 | template <typename T> | |||
50 | struct QScopedPointerDeleter | |||
51 | { | |||
52 | static inline void cleanup(T *pointer) | |||
53 | { | |||
54 | // Enforce a complete type. | |||
55 | // If you get a compile error here, read the section on forward declared | |||
56 | // classes in the QScopedPointer documentation. | |||
57 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; | |||
58 | (void) sizeof(IsIncompleteType); | |||
59 | ||||
60 | delete pointer; | |||
| ||||
61 | } | |||
62 | }; | |||
63 | ||||
64 | template <typename T> | |||
65 | struct QScopedPointerArrayDeleter | |||
66 | { | |||
67 | static inline void cleanup(T *pointer) | |||
68 | { | |||
69 | // Enforce a complete type. | |||
70 | // If you get a compile error here, read the section on forward declared | |||
71 | // classes in the QScopedPointer documentation. | |||
72 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; | |||
73 | (void) sizeof(IsIncompleteType); | |||
74 | ||||
75 | delete [] pointer; | |||
76 | } | |||
77 | }; | |||
78 | ||||
79 | struct QScopedPointerPodDeleter | |||
80 | { | |||
81 | static inline void cleanup(void *pointer) { if (pointer) free(pointer); } | |||
82 | }; | |||
83 | ||||
84 | #ifndef QT_NO_QOBJECT | |||
85 | template <typename T> | |||
86 | struct QScopedPointerObjectDeleteLater | |||
87 | { | |||
88 | static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); } | |||
89 | }; | |||
90 | ||||
91 | class QObject; | |||
92 | typedef QScopedPointerObjectDeleteLater<QObject> QScopedPointerDeleteLater; | |||
93 | #endif | |||
94 | ||||
95 | template <typename T, typename Cleanup = QScopedPointerDeleter<T> > | |||
96 | class QScopedPointer | |||
97 | { | |||
98 | typedef T *QScopedPointer:: *RestrictedBool; | |||
99 | public: | |||
100 | explicit QScopedPointer(T *p = nullptr) Q_DECL_NOTHROWnoexcept : d(p) | |||
101 | { | |||
102 | } | |||
103 | ||||
104 | inline ~QScopedPointer() | |||
105 | { | |||
106 | T *oldD = this->d; | |||
107 | Cleanup::cleanup(oldD); | |||
108 | } | |||
109 | ||||
110 | inline T &operator*() const | |||
111 | { | |||
112 | Q_ASSERT(d)((d) ? static_cast<void>(0) : qt_assert("d", "/usr/lib64/qt5/include/QtCore/qscopedpointer.h" , 112)); | |||
113 | return *d; | |||
114 | } | |||
115 | ||||
116 | T *operator->() const Q_DECL_NOTHROWnoexcept | |||
117 | { | |||
118 | return d; | |||
119 | } | |||
120 | ||||
121 | bool operator!() const Q_DECL_NOTHROWnoexcept | |||
122 | { | |||
123 | return !d; | |||
124 | } | |||
125 | ||||
126 | #if defined(Q_QDOC) | |||
127 | inline operator bool() const | |||
128 | { | |||
129 | return isNull() ? nullptr : &QScopedPointer::d; | |||
130 | } | |||
131 | #else | |||
132 | operator RestrictedBool() const Q_DECL_NOTHROWnoexcept | |||
133 | { | |||
134 | return isNull() ? nullptr : &QScopedPointer::d; | |||
135 | } | |||
136 | #endif | |||
137 | ||||
138 | T *data() const Q_DECL_NOTHROWnoexcept | |||
139 | { | |||
140 | return d; | |||
141 | } | |||
142 | ||||
143 | T *get() const Q_DECL_NOTHROWnoexcept | |||
144 | { | |||
145 | return d; | |||
146 | } | |||
147 | ||||
148 | bool isNull() const Q_DECL_NOTHROWnoexcept | |||
149 | { | |||
150 | return !d; | |||
151 | } | |||
152 | ||||
153 | void reset(T *other = nullptr) Q_DECL_NOEXCEPT_EXPR(noexcept(Cleanup::cleanup(std::declval<T *>())))noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()) )) | |||
154 | { | |||
155 | if (d == other) | |||
156 | return; | |||
157 | T *oldD = d; | |||
158 | d = other; | |||
159 | Cleanup::cleanup(oldD); | |||
160 | } | |||
161 | ||||
162 | T *take() Q_DECL_NOTHROWnoexcept | |||
163 | { | |||
164 | T *oldD = d; | |||
165 | d = nullptr; | |||
166 | return oldD; | |||
167 | } | |||
168 | ||||
169 | void swap(QScopedPointer<T, Cleanup> &other) Q_DECL_NOTHROWnoexcept | |||
170 | { | |||
171 | qSwap(d, other.d); | |||
172 | } | |||
173 | ||||
174 | typedef T *pointer; | |||
175 | ||||
176 | protected: | |||
177 | T *d; | |||
178 | ||||
179 | private: | |||
180 | Q_DISABLE_COPY(QScopedPointer)QScopedPointer(const QScopedPointer &) = delete; QScopedPointer &operator=(const QScopedPointer &) = delete; | |||
181 | }; | |||
182 | ||||
183 | template <class T, class Cleanup> | |||
184 | inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) Q_DECL_NOTHROWnoexcept | |||
185 | { | |||
186 | return lhs.data() == rhs.data(); | |||
187 | } | |||
188 | ||||
189 | template <class T, class Cleanup> | |||
190 | inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) Q_DECL_NOTHROWnoexcept | |||
191 | { | |||
192 | return lhs.data() != rhs.data(); | |||
193 | } | |||
194 | ||||
195 | template <class T, class Cleanup> | |||
196 | inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) Q_DECL_NOTHROWnoexcept | |||
197 | { | |||
198 | return lhs.isNull(); | |||
199 | } | |||
200 | ||||
201 | template <class T, class Cleanup> | |||
202 | inline bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) Q_DECL_NOTHROWnoexcept | |||
203 | { | |||
204 | return rhs.isNull(); | |||
205 | } | |||
206 | ||||
207 | template <class T, class Cleanup> | |||
208 | inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) Q_DECL_NOTHROWnoexcept | |||
209 | { | |||
210 | return !lhs.isNull(); | |||
211 | } | |||
212 | ||||
213 | template <class T, class Cleanup> | |||
214 | inline bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) Q_DECL_NOTHROWnoexcept | |||
215 | { | |||
216 | return !rhs.isNull(); | |||
217 | } | |||
218 | ||||
219 | template <class T, class Cleanup> | |||
220 | inline void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) Q_DECL_NOTHROWnoexcept | |||
221 | { p1.swap(p2); } | |||
222 | ||||
223 | template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > | |||
224 | class QScopedArrayPointer : public QScopedPointer<T, Cleanup> | |||
225 | { | |||
226 | template <typename Ptr> | |||
227 | using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type; | |||
228 | public: | |||
229 | inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(nullptr) {} | |||
230 | ||||
231 | template <typename D, if_same_type<D> = true> | |||
232 | explicit QScopedArrayPointer(D *p) | |||
233 | : QScopedPointer<T, Cleanup>(p) | |||
234 | { | |||
235 | } | |||
236 | ||||
237 | inline T &operator[](int i) | |||
238 | { | |||
239 | return this->d[i]; | |||
240 | } | |||
241 | ||||
242 | inline const T &operator[](int i) const | |||
243 | { | |||
244 | return this->d[i]; | |||
245 | } | |||
246 | ||||
247 | void swap(QScopedArrayPointer &other) Q_DECL_NOTHROWnoexcept // prevent QScopedPointer <->QScopedArrayPointer swaps | |||
248 | { QScopedPointer<T, Cleanup>::swap(other); } | |||
249 | ||||
250 | private: | |||
251 | explicit inline QScopedArrayPointer(void *) { | |||
252 | // Enforce the same type. | |||
253 | ||||
254 | // If you get a compile error here, make sure you declare | |||
255 | // QScopedArrayPointer with the same template type as you pass to the | |||
256 | // constructor. See also the QScopedPointer documentation. | |||
257 | ||||
258 | // Storing a scalar array as a pointer to a different type is not | |||
259 | // allowed and results in undefined behavior. | |||
260 | } | |||
261 | ||||
262 | Q_DISABLE_COPY(QScopedArrayPointer)QScopedArrayPointer(const QScopedArrayPointer &) = delete ; QScopedArrayPointer &operator=(const QScopedArrayPointer &) = delete; | |||
263 | }; | |||
264 | ||||
265 | template <typename T, typename Cleanup> | |||
266 | inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) Q_DECL_NOTHROWnoexcept | |||
267 | { lhs.swap(rhs); } | |||
268 | ||||
269 | QT_END_NAMESPACE | |||
270 | ||||
271 | #endif // QSCOPEDPOINTER_H |
File: | mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp |
Warning: | line 237, column 1 Potential leak of memory pointed to by 'item' |
Press '?' to see keyboard shortcuts
-Keyboard shortcuts:
1 | /* ============================================================ | |||
2 | * | |||
3 | * This file is a part of digiKam project | |||
4 | * https://www.digikam.org | |||
5 | * | |||
6 | * Date : 2005-03-27 | |||
7 | * Description : a digiKam image tool for fixing dots produced by | |||
8 | * hot/stuck/dead pixels from a CCD. | |||
9 | * | |||
10 | * Copyright (C) 2005-2019 by Gilles Caulier <caulier dot gilles at gmail dot com> | |||
11 | * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net> | |||
12 | * | |||
13 | * This program is free software; you can redistribute it | |||
14 | * and/or modify it under the terms of the GNU General | |||
15 | * Public License as published by the Free Software Foundation; | |||
16 | * either version 2, or (at your option) | |||
17 | * any later version. | |||
18 | * | |||
19 | * This program 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 | * ============================================================ */ | |||
25 | ||||
26 | #include "hotpixelstool.h" | |||
27 | ||||
28 | // Qt includes | |||
29 | ||||
30 | #include <QGridLayout> | |||
31 | #include <QLabel> | |||
32 | #include <QPolygon> | |||
33 | #include <QProgressBar> | |||
34 | #include <QPushButton> | |||
35 | #include <QIcon> | |||
36 | #include <QApplication> | |||
37 | ||||
38 | // KDE includes | |||
39 | ||||
40 | #include <klocalizedstring.h> | |||
41 | #include <ksharedconfig.h> | |||
42 | #include "kconfiggroup.h" | |||
43 | ||||
44 | // Local includes | |||
45 | ||||
46 | #include "blackframelistview.h" | |||
47 | #include "dcombobox.h" | |||
48 | #include "daboutdata.h" | |||
49 | #include "dimg.h" | |||
50 | #include "dimgfiltermanager.h" | |||
51 | #include "editortooliface.h" | |||
52 | #include "editortoolsettings.h" | |||
53 | #include "hotpixelfixer.h" | |||
54 | #include "imagedialog.h" | |||
55 | #include "imageiface.h" | |||
56 | #include "imageregionwidget.h" | |||
57 | ||||
58 | namespace DigikamEditorHotPixelsToolPlugin | |||
59 | { | |||
60 | ||||
61 | class Q_DECL_HIDDEN__attribute__((visibility("hidden"))) HotPixelsTool::Private | |||
62 | { | |||
63 | public: | |||
64 | ||||
65 | explicit Private() | |||
66 | : blackFrameButton(nullptr), | |||
67 | progressBar(nullptr), | |||
68 | filterMethodCombo(nullptr), | |||
69 | blackFrameListView(nullptr), | |||
70 | previewWidget(nullptr), | |||
71 | gboxSettings(nullptr) | |||
72 | { | |||
73 | } | |||
74 | ||||
75 | static const QString configGroupName; | |||
76 | static const QString configLastBlackFrameFileEntry; | |||
77 | static const QString configFilterMethodEntry; | |||
78 | ||||
79 | QPushButton* blackFrameButton; | |||
80 | QProgressBar* progressBar; | |||
81 | QList<HotPixel> hotPixelsList; | |||
82 | ||||
83 | QUrl blackFrameURL; | |||
84 | ||||
85 | DComboBox* filterMethodCombo; | |||
86 | ||||
87 | BlackFrameListView* blackFrameListView; | |||
88 | ImageRegionWidget* previewWidget; | |||
89 | EditorToolSettings* gboxSettings; | |||
90 | }; | |||
91 | ||||
92 | const QString HotPixelsTool::Private::configGroupName(QLatin1String("hotpixels Tool")); | |||
93 | const QString HotPixelsTool::Private::configLastBlackFrameFileEntry(QLatin1String("Last Black Frame File")); | |||
94 | const QString HotPixelsTool::Private::configFilterMethodEntry(QLatin1String("Filter Method")); | |||
95 | ||||
96 | // -------------------------------------------------------- | |||
97 | ||||
98 | HotPixelsTool::HotPixelsTool(QObject* const parent) | |||
99 | : EditorToolThreaded(parent), | |||
100 | d(new Private) | |||
101 | { | |||
102 | setObjectName(QLatin1String("hotpixels")); | |||
103 | setToolName(i18n("Hot Pixels")i18nd("digikam", "Hot Pixels")); | |||
104 | setToolIcon(QIcon::fromTheme(QLatin1String("hotpixels"))); | |||
105 | ||||
106 | // ------------------------------------------------------------- | |||
107 | ||||
108 | d->gboxSettings = new EditorToolSettings(nullptr); | |||
109 | d->gboxSettings->setButtons(EditorToolSettings::Default| | |||
110 | EditorToolSettings::Ok| | |||
111 | EditorToolSettings::Cancel| | |||
112 | EditorToolSettings::Try); | |||
113 | ||||
114 | QGridLayout* const grid = new QGridLayout(d->gboxSettings->plainPage()); | |||
115 | ||||
116 | QLabel* const filterMethodLabel = new QLabel(i18n("Filter:")i18nd("digikam", "Filter:"), d->gboxSettings->plainPage()); | |||
117 | d->filterMethodCombo = new DComboBox(d->gboxSettings->plainPage()); | |||
118 | d->filterMethodCombo->addItem(i18nc("average filter mode", "Average")i18ndc("digikam", "average filter mode", "Average")); | |||
119 | d->filterMethodCombo->addItem(i18nc("linear filter mode", "Linear")i18ndc("digikam", "linear filter mode", "Linear")); | |||
120 | d->filterMethodCombo->addItem(i18nc("quadratic filter mode", "Quadratic")i18ndc("digikam", "quadratic filter mode", "Quadratic")); | |||
121 | d->filterMethodCombo->addItem(i18nc("cubic filter mode", "Cubic")i18ndc("digikam", "cubic filter mode", "Cubic")); | |||
122 | d->filterMethodCombo->setDefaultIndex(HotPixelFixer::QUADRATIC_INTERPOLATION); | |||
123 | ||||
124 | d->blackFrameButton = new QPushButton(i18n("Black Frame...")i18nd("digikam", "Black Frame..."), d->gboxSettings->plainPage()); | |||
125 | d->blackFrameButton->setIcon(QIcon::fromTheme(QLatin1String("document-open"))); | |||
126 | d->blackFrameButton->setWhatsThis(i18n("Use this button to add a new black frame file which will "i18nd("digikam", "Use this button to add a new black frame file which will " "be used by the hot pixels removal filter.") | |||
127 | "be used by the hot pixels removal filter.")i18nd("digikam", "Use this button to add a new black frame file which will " "be used by the hot pixels removal filter.") ); | |||
128 | ||||
129 | d->blackFrameListView = new BlackFrameListView(d->gboxSettings->plainPage()); | |||
130 | ||||
131 | // ------------------------------------------------------------- | |||
132 | ||||
133 | const int spacing = d->gboxSettings->spacingHint(); | |||
134 | ||||
135 | grid->addWidget(filterMethodLabel, 0, 0, 1, 1); | |||
136 | grid->addWidget(d->filterMethodCombo, 0, 1, 1, 1); | |||
137 | grid->addWidget(d->blackFrameButton, 0, 2, 1, 1); | |||
138 | grid->addWidget(d->blackFrameListView, 1, 0, 2, 3); | |||
139 | grid->setRowStretch(3, 10); | |||
140 | grid->setContentsMargins(spacing, spacing, spacing, spacing); | |||
141 | grid->setSpacing(spacing); | |||
142 | ||||
143 | // ------------------------------------------------------------- | |||
144 | ||||
145 | d->previewWidget = new ImageRegionWidget; | |||
146 | ||||
147 | setToolSettings(d->gboxSettings); | |||
148 | setToolView(d->previewWidget); | |||
149 | setPreviewModeMask(PreviewToolBar::AllPreviewModes); | |||
150 | ||||
151 | // ------------------------------------------------------------- | |||
152 | ||||
153 | connect(d->filterMethodCombo, SIGNAL(activated(int))qFlagLocation("2""activated(int)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "153"), | |||
154 | this, SLOT(slotPreview())qFlagLocation("1""slotPreview()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "154")); | |||
155 | ||||
156 | connect(d->blackFrameButton, SIGNAL(clicked())qFlagLocation("2""clicked()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "156"), | |||
157 | this, SLOT(slotAddBlackFrame())qFlagLocation("1""slotAddBlackFrame()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "157")); | |||
158 | ||||
159 | connect(d->blackFrameListView, SIGNAL(signalBlackFrameSelected(QList<HotPixel>,QUrl))qFlagLocation("2""signalBlackFrameSelected(QList<HotPixel>,QUrl)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "159"), | |||
160 | this, SLOT(slotBlackFrame(QList<HotPixel>,QUrl))qFlagLocation("1""slotBlackFrame(QList<HotPixel>,QUrl)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "160")); | |||
161 | } | |||
162 | ||||
163 | HotPixelsTool::~HotPixelsTool() | |||
164 | { | |||
165 | delete d; | |||
166 | } | |||
167 | ||||
168 | void HotPixelsTool::registerFilter() | |||
169 | { | |||
170 | DImgFilterManager::instance()->addGenerator(new BasicDImgFilterGenerator<HotPixelFixer>()); | |||
171 | } | |||
172 | ||||
173 | void HotPixelsTool::readSettings() | |||
174 | { | |||
175 | KSharedConfig::Ptr config = KSharedConfig::openConfig(); | |||
176 | KConfigGroup group = config->group(d->configGroupName); | |||
177 | d->blackFrameURL = QUrl::fromLocalFile(group.readEntry(d->configLastBlackFrameFileEntry, QString())); | |||
178 | d->filterMethodCombo->setCurrentIndex(group.readEntry(d->configFilterMethodEntry, d->filterMethodCombo->defaultIndex())); | |||
179 | ||||
180 | if (d->blackFrameURL.isValid()) | |||
181 | { | |||
182 | EditorToolIface::editorToolIface()->setToolStartProgress(i18n("Loading: ")i18nd("digikam", "Loading: ")); | |||
183 | BlackFrameListViewItem* item = new BlackFrameListViewItem(d->blackFrameListView, d->blackFrameURL); | |||
183 | BlackFrameListViewItem* const item = new BlackFrameListViewItem(d->blackFrameListView, d->blackFrameURL); | |||
184 | ||||
185 | connect(item, SIGNAL(signalLoadingProgress(float))qFlagLocation("2""signalLoadingProgress(float)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "185"), | |||
186 | this, SLOT(slotLoadingProgress(float))qFlagLocation("1""slotLoadingProgress(float)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "186")); | |||
187 | ||||
188 | connect(item, SIGNAL(signalLoadingComplete())qFlagLocation("2""signalLoadingComplete()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "188"), | |||
189 | this, SLOT(slotLoadingComplete())qFlagLocation("1""slotLoadingComplete()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "189")); | |||
190 | } | |||
191 | } | |||
192 | ||||
193 | void HotPixelsTool::writeSettings() | |||
194 | { | |||
195 | KSharedConfig::Ptr config = KSharedConfig::openConfig(); | |||
196 | KConfigGroup group = config->group(d->configGroupName); | |||
197 | group.writeEntry(d->configLastBlackFrameFileEntry, d->blackFrameURL.url()); | |||
198 | group.writeEntry(d->configFilterMethodEntry, d->filterMethodCombo->currentIndex()); | |||
199 | group.sync(); | |||
200 | } | |||
201 | ||||
202 | void HotPixelsTool::slotLoadingProgress(float v) | |||
203 | { | |||
204 | EditorToolIface::editorToolIface()->setToolProgress((int)(v*100)); | |||
205 | } | |||
206 | ||||
207 | void HotPixelsTool::slotLoadingComplete() | |||
208 | { | |||
209 | EditorToolIface::editorToolIface()->setToolStopProgress(); | |||
210 | } | |||
211 | ||||
212 | void HotPixelsTool::slotResetSettings() | |||
213 | { | |||
214 | d->filterMethodCombo->blockSignals(true); | |||
215 | d->filterMethodCombo->slotReset(); | |||
216 | d->filterMethodCombo->blockSignals(false); | |||
217 | } | |||
218 | ||||
219 | void HotPixelsTool::slotAddBlackFrame() | |||
220 | { | |||
221 | QUrl url = ImageDialog::getImageURL(qApp(static_cast<QApplication *>(QCoreApplication::instance ()))->activeWindow(), d->blackFrameURL, i18n("Select Black Frame Image")i18nd("digikam", "Select Black Frame Image")); | |||
222 | ||||
223 | if (!url.isEmpty()) | |||
| ||||
224 | { | |||
225 | // Load the selected file and insert into the list. | |||
226 | ||||
227 | d->blackFrameURL = url; | |||
228 | d->blackFrameListView->clear(); | |||
229 | BlackFrameListViewItem* item = new BlackFrameListViewItem(d->blackFrameListView, d->blackFrameURL); | |||
229 | BlackFrameListViewItem* const item = new BlackFrameListViewItem(d->blackFrameListView, d->blackFrameURL); | |||
230 | ||||
231 | connect(item, SIGNAL(signalLoadingProgress(float))qFlagLocation("2""signalLoadingProgress(float)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "231"), | |||
232 | this, SLOT(slotLoadingProgress(float))qFlagLocation("1""slotLoadingProgress(float)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "232")); | |||
233 | ||||
234 | connect(item, SIGNAL(signalLoadingComplete())qFlagLocation("2""signalLoadingComplete()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "234"), | |||
235 | this, SLOT(slotLoadingComplete())qFlagLocation("1""slotLoadingComplete()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "235")); | |||
236 | } | |||
237 | } | |||
| ||||
238 | ||||
239 | void HotPixelsTool::preparePreview() | |||
240 | { | |||
241 | DImg image = d->previewWidget->getOriginalRegionImage(); | |||
242 | int interpolationMethod = d->filterMethodCombo->currentIndex(); | |||
243 | ||||
244 | QList<HotPixel> hotPixelsRegion; | |||
245 | QRect area = d->previewWidget->getOriginalImageRegionToRender(); | |||
246 | ||||
247 | for (QList<HotPixel>::const_iterator it = d->hotPixelsList.constBegin() ; it != d->hotPixelsList.constEnd() ; ++it) | |||
248 | { | |||
249 | HotPixel hp = (*it); | |||
250 | ||||
251 | if (area.contains( hp.rect )) | |||
252 | { | |||
253 | hp.rect.moveTopLeft(QPoint( hp.rect.x()-area.x(), hp.rect.y()-area.y() )); | |||
254 | hotPixelsRegion.append(hp); | |||
255 | } | |||
256 | } | |||
257 | ||||
258 | setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(&image, this, hotPixelsRegion, interpolationMethod))); | |||
259 | } | |||
260 | ||||
261 | void HotPixelsTool::prepareFinal() | |||
262 | { | |||
263 | int interpolationMethod = d->filterMethodCombo->currentIndex(); | |||
264 | ||||
265 | ImageIface iface; | |||
266 | setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(iface.original(), this, d->hotPixelsList, interpolationMethod))); | |||
267 | } | |||
268 | ||||
269 | void HotPixelsTool::setPreviewImage() | |||
270 | { | |||
271 | d->previewWidget->setPreviewImage(filter()->getTargetImage()); | |||
272 | } | |||
273 | ||||
274 | void HotPixelsTool::setFinalImage() | |||
275 | { | |||
276 | ImageIface iface; | |||
277 | iface.setOriginal(i18n("Hot Pixels Correction")i18nd("digikam", "Hot Pixels Correction"), filter()->filterAction(), filter()->getTargetImage()); | |||
278 | } | |||
279 | ||||
280 | void HotPixelsTool::slotBlackFrame(const QList<HotPixel>& hpList, const QUrl& blackFrameURL) | |||
281 | { | |||
282 | d->blackFrameURL = blackFrameURL; | |||
283 | d->hotPixelsList = hpList; | |||
284 | ||||
285 | QPolygon pointList(d->hotPixelsList.size()); | |||
286 | QList <HotPixel>::const_iterator it; | |||
287 | int i = 0; | |||
288 | ||||
289 | for (it = d->hotPixelsList.constBegin() ; it != d->hotPixelsList.constEnd() ; ++it, ++i) | |||
290 | { | |||
291 | pointList.setPoint(i, (*it).rect.center()); | |||
292 | } | |||
293 | ||||
294 | d->previewWidget->setHighLightPoints(pointList); | |||
295 | ||||
296 | slotPreview(); | |||
297 | } | |||
298 | ||||
299 | } // namespace DigikamEditorHotPixelsToolPlugin | |||
247 | for (QList<HotPixel>::const_iterator it = d->hotPixelsList.constBegin() ; | |||
248 | it != d->hotPixelsList.constEnd() ; ++it) | |||
249 | { | |||
250 | HotPixel hp = (*it); | |||
251 | ||||
252 | if (area.contains( hp.rect )) | |||
253 | { | |||
254 | hp.rect.moveTopLeft(QPoint( hp.rect.x()-area.x(), hp.rect.y()-area.y() )); | |||
255 | hotPixelsRegion.append(hp); | |||
256 | } | |||
257 | } | |||
258 | ||||
259 | setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(&image, this, hotPixelsRegion, interpolationMethod))); | |||
260 | } | |||
261 | ||||
262 | void HotPixelsTool::prepareFinal() | |||
263 | { | |||
264 | int interpolationMethod = d->filterMethodCombo->currentIndex(); | |||
265 | ||||
266 | ImageIface iface; | |||
267 | setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(iface.original(), this, d->hotPixelsList, interpolationMethod))); | |||
268 | } | |||
269 | ||||
270 | void HotPixelsTool::setPreviewImage() | |||
271 | { | |||
272 | d->previewWidget->setPreviewImage(filter()->getTargetImage()); | |||
273 | } | |||
274 | ||||
275 | void HotPixelsTool::setFinalImage() | |||
276 | { | |||
277 | ImageIface iface; | |||
278 | iface.setOriginal(i18n("Hot Pixels Correction")i18nd("digikam", "Hot Pixels Correction"), filter()->filterAction(), filter()->getTargetImage()); | |||
279 | } | |||
280 | ||||
281 | void HotPixelsTool::slotBlackFrame(const QList<HotPixel>& hpList, const QUrl& blackFrameURL) | |||
282 | { | |||
283 | d->blackFrameURL = blackFrameURL; | |||
284 | d->hotPixelsList = hpList; | |||
285 | ||||
286 | QPolygon pointList(d->hotPixelsList.size()); | |||
287 | QList <HotPixel>::const_iterator it; | |||
288 | int i = 0; | |||
289 | ||||
290 | for (it = d->hotPixelsList.constBegin() ; it != d->hotPixelsList.constEnd() ; ++it, ++i) | |||
291 | { | |||
292 | pointList.setPoint(i, (*it).rect.center()); | |||
293 | } | |||
294 | ||||
295 | d->previewWidget->setHighLightPoints(pointList); | |||
296 | ||||
297 | slotPreview(); | |||
298 | } | |||
299 | ||||
300 | } // namespace DigikamEditorHotPixelsToolPlugin |
File: | usr/lib64/qt5/include/QtCore/qshareddata.h |
Warning: | line 161, column 41 Use of memory after it is freed |
Warning: | line 159, column 36 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
-Keyboard shortcuts:
1 | /* ============================================================ | |||
2 | * | |||
3 | * This file is a part of digiKam project | |||
4 | * https://www.digikam.org | |||
5 | * | |||
6 | * Date : 2005-06-14 | |||
7 | * Description : digiKam 8/16 bits image management API. | |||
8 | * Data management. | |||
9 | * | |||
10 | * Copyright (C) 2005-2019 by Gilles Caulier <caulier dot gilles at gmail dot com> | |||
11 | * Copyright (C) 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> | |||
12 | * | |||
13 | * This program is free software; you can redistribute it | |||
14 | * and/or modify it under the terms of the GNU General | |||
15 | * Public License as published by the Free Software Foundation; | |||
16 | * either version 2, or (at your option) | |||
17 | * any later version. | |||
18 | * | |||
19 | * This program 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 | * ============================================================ */ | |||
25 | ||||
26 | #include "dimg_p.h" | |||
27 | ||||
28 | namespace Digikam | |||
29 | { | |||
30 | ||||
31 | DImg& DImg::operator=(const DImg& image) | |||
32 | { | |||
33 | m_priv = image.m_priv; | |||
34 | return *this; | |||
35 | } | |||
36 | ||||
37 | bool DImg::operator==(const DImg& image) const | |||
38 | { | |||
39 | return m_priv == image.m_priv; | |||
40 | } | |||
41 | ||||
42 | void DImg::reset() | |||
43 | { | |||
44 | m_priv = new Private; | |||
45 | } | |||
46 | ||||
47 | void DImg::detach() | |||
48 | { | |||
49 | // are we being shared? | |||
50 | if (m_priv->ref == 1) | |||
| ||||
51 | { | |||
52 | return; | |||
53 | } | |||
54 | ||||
55 | QExplicitlySharedDataPointer<Private> old = m_priv; | |||
56 | ||||
57 | m_priv = new Private; | |||
58 | copyImageData(old.constData()); | |||
59 | copyMetaData(old.constData()); | |||
58 | copyImageData(old); | |||
59 | copyMetaData(old); | |||
60 | ||||
61 | if (old->data) | |||
62 | { | |||
63 | size_t size = allocateData(); | |||
64 | memcpy(m_priv->data, old->data, size); | |||
65 | } | |||
66 | } | |||
67 | ||||
68 | void DImg::putImageData(uint width, uint height, bool sixteenBit, bool alpha, uchar* const data, bool copyData) | |||
69 | { | |||
70 | // set image data, metadata is untouched | |||
71 | ||||
72 | bool null = (width == 0) || (height == 0); | |||
73 | // allocateData, or code below will set null to false | |||
74 | setImageData(true, width, height, sixteenBit, alpha); | |||
75 | ||||
76 | // replace data | |||
77 | delete [] m_priv->data; | |||
78 | ||||
79 | if (null) | |||
80 | { | |||
81 | // image is null - no data | |||
82 | m_priv->data = nullptr; | |||
83 | } | |||
84 | else if (copyData) | |||
85 | { | |||
86 | size_t size = allocateData(); | |||
87 | ||||
88 | if (data) | |||
89 | { | |||
90 | memcpy(m_priv->data, data, size); | |||
91 | } | |||
92 | } | |||
93 | else | |||
94 | { | |||
95 | if (data) | |||
96 | { | |||
97 | m_priv->data = data; | |||
98 | m_priv->null = false; | |||
99 | } | |||
100 | else | |||
101 | { | |||
102 | allocateData(); | |||
103 | } | |||
104 | } | |||
105 | } | |||
106 | ||||
107 | void DImg::putImageData(uchar* const data, bool copyData) | |||
108 | { | |||
109 | if (!data) | |||
110 | { | |||
111 | delete [] m_priv->data; | |||
112 | m_priv->data = nullptr; | |||
113 | m_priv->null = true; | |||
114 | } | |||
115 | else if (copyData) | |||
116 | { | |||
117 | memcpy(m_priv->data, data, numBytes()); | |||
118 | } | |||
119 | else | |||
120 | { | |||
121 | m_priv->data = data; | |||
122 | } | |||
123 | } | |||
124 | ||||
125 | void DImg::resetMetaData() | |||
126 | { | |||
127 | m_priv->attributes.clear(); | |||
128 | m_priv->embeddedText.clear(); | |||
129 | m_priv->metaData = MetaEngineData(); | |||
130 | } | |||
131 | ||||
132 | uchar* DImg::stripImageData() | |||
133 | { | |||
134 | uchar* const data = m_priv->data; | |||
135 | m_priv->data = nullptr; | |||
136 | m_priv->null = true; | |||
137 | m_priv->width = 0; | |||
138 | m_priv->height = 0; | |||
139 | return data; | |||
140 | } | |||
141 | ||||
142 | void DImg::copyMetaData(const Private* const src) | |||
142 | void DImg::copyMetaData(const QExplicitlySharedDataPointer<Private>& src) | |||
143 | { | |||
144 | m_priv->metaData = src->metaData; | |||
145 | m_priv->attributes = src->attributes; | |||
146 | m_priv->embeddedText = src->embeddedText; | |||
147 | m_priv->iccProfile = src->iccProfile; | |||
148 | m_priv->imageHistory = src->imageHistory; | |||
149 | //FIXME: what about sharing and deleting lanczos_func? | |||
150 | } | |||
151 | ||||
152 | void DImg::copyImageData(const Private* const src) | |||
152 | void DImg::copyImageData(const QExplicitlySharedDataPointer<Private>& src) | |||
153 | { | |||
154 | setImageData(src->null, src->width, src->height, src->sixteenBit, src->alpha); | |||
154 | setImageData(src->null, src->width, src->height, src->sixteenBit, src->alpha); | |||
155 | } | |||
156 | ||||
157 | size_t DImg::allocateData() | |||
158 | { | |||
159 | size_t size = m_priv->width * m_priv->height * (m_priv->sixteenBit ? 8 : 4); | |||
160 | m_priv->data = DImgLoader::new_failureTolerant(size); | |||
161 | ||||
162 | if (!m_priv->data) | |||
163 | { | |||
164 | m_priv->null = true; | |||
165 | m_priv->width = 0; | |||
166 | m_priv->height = 0; | |||
167 | return 0; | |||
168 | } | |||
169 | ||||
170 | m_priv->null = false; | |||
171 | return size; | |||
172 | } | |||
173 | ||||
174 | void DImg::setImageDimension(uint width, uint height) | |||
175 | { | |||
176 | m_priv->width = width; | |||
177 | m_priv->height = height; | |||
178 | } | |||
179 | ||||
180 | void DImg::setImageData(bool null, uint width, uint height, bool sixteenBit, bool alpha) | |||
181 | { | |||
182 | m_priv->null = null; | |||
183 | m_priv->width = width; | |||
184 | m_priv->height = height; | |||
185 | m_priv->alpha = alpha; | |||
186 | m_priv->sixteenBit = sixteenBit; | |||
187 | } | |||
188 | ||||
189 | } // namespace Digikam |
1 | /**************************************************************************** | |||
2 | ** | |||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | |||
4 | ** Contact: https://www.qt.io/licensing/ | |||
5 | ** | |||
6 | ** This file is part of the QtCore module of the Qt Toolkit. | |||
7 | ** | |||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | |||
9 | ** Commercial License Usage | |||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | |||
11 | ** accordance with the commercial license agreement provided with the | |||
12 | ** Software or, alternatively, in accordance with the terms contained in | |||
13 | ** a written agreement between you and The Qt Company. For licensing terms | |||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | |||
15 | ** information use the contact form at https://www.qt.io/contact-us. | |||
16 | ** | |||
17 | ** GNU Lesser General Public License Usage | |||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | |||
19 | ** General Public License version 3 as published by the Free Software | |||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | |||
21 | ** packaging of this file. Please review the following information to | |||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | |||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | |||
24 | ** | |||
25 | ** GNU General Public License Usage | |||
26 | ** Alternatively, this file may be used under the terms of the GNU | |||
27 | ** General Public License version 2.0 or (at your option) the GNU General | |||
28 | ** Public license version 3 or any later version approved by the KDE Free | |||
29 | ** Qt Foundation. The licenses are as published by the Free Software | |||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | |||
31 | ** included in the packaging of this file. Please review the following | |||
32 | ** information to ensure the GNU General Public License requirements will | |||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | |||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | |||
35 | ** | |||
36 | ** $QT_END_LICENSE$ | |||
37 | ** | |||
38 | ****************************************************************************/ | |||
39 | ||||
40 | #ifndef QSHAREDDATA_H | |||
41 | #define QSHAREDDATA_H | |||
42 | ||||
43 | #include <QtCore/qglobal.h> | |||
44 | #include <QtCore/qatomic.h> | |||
45 | #if QT_DEPRECATED_SINCE(5, 6)(((5<<16)|(6<<8)|(0)) > ((5<<16)|(0<< 8)|(0))) | |||
46 | #include <QtCore/qhash.h> | |||
47 | #endif | |||
48 | #include <QtCore/qhashfunctions.h> | |||
49 | ||||
50 | QT_BEGIN_NAMESPACE | |||
51 | ||||
52 | ||||
53 | template <class T> class QSharedDataPointer; | |||
54 | ||||
55 | class Q_CORE_EXPORT__attribute__((visibility("default"))) QSharedData | |||
56 | { | |||
57 | public: | |||
58 | mutable QAtomicInt ref; | |||
59 | ||||
60 | inline QSharedData() : ref(0) { } | |||
61 | inline QSharedData(const QSharedData &) : ref(0) { } | |||
62 | ||||
63 | private: | |||
64 | // using the assignment operator would lead to corruption in the ref-counting | |||
65 | QSharedData &operator=(const QSharedData &); | |||
66 | }; | |||
67 | ||||
68 | template <class T> class QSharedDataPointer | |||
69 | { | |||
70 | public: | |||
71 | typedef T Type; | |||
72 | typedef T *pointer; | |||
73 | ||||
74 | inline void detach() { if (d && d->ref.load() != 1) detach_helper(); } | |||
75 | inline T &operator*() { detach(); return *d; } | |||
76 | inline const T &operator*() const { return *d; } | |||
77 | inline T *operator->() { detach(); return d; } | |||
78 | inline const T *operator->() const { return d; } | |||
79 | inline operator T *() { detach(); return d; } | |||
80 | inline operator const T *() const { return d; } | |||
81 | inline T *data() { detach(); return d; } | |||
82 | inline const T *data() const { return d; } | |||
83 | inline const T *constData() const { return d; } | |||
84 | ||||
85 | inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; } | |||
86 | inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; } | |||
87 | ||||
88 | inline QSharedDataPointer() { d = nullptr; } | |||
89 | inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; } | |||
90 | ||||
91 | explicit QSharedDataPointer(T *data) Q_DECL_NOTHROWnoexcept; | |||
92 | inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } | |||
93 | inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) { | |||
94 | if (o.d != d) { | |||
95 | if (o.d) | |||
96 | o.d->ref.ref(); | |||
97 | T *old = d; | |||
98 | d = o.d; | |||
99 | if (old && !old->ref.deref()) | |||
100 | delete old; | |||
101 | } | |||
102 | return *this; | |||
103 | } | |||
104 | inline QSharedDataPointer &operator=(T *o) { | |||
105 | if (o != d) { | |||
106 | if (o) | |||
107 | o->ref.ref(); | |||
108 | T *old = d; | |||
109 | d = o; | |||
110 | if (old && !old->ref.deref()) | |||
111 | delete old; | |||
112 | } | |||
113 | return *this; | |||
114 | } | |||
115 | #ifdef Q_COMPILER_RVALUE_REFS | |||
116 | QSharedDataPointer(QSharedDataPointer &&o) Q_DECL_NOTHROWnoexcept : d(o.d) { o.d = nullptr; } | |||
117 | inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) Q_DECL_NOTHROWnoexcept | |||
118 | { | |||
119 | QSharedDataPointer moved(std::move(other)); | |||
120 | swap(moved); | |||
121 | return *this; | |||
122 | } | |||
123 | #endif | |||
124 | ||||
125 | inline bool operator!() const { return !d; } | |||
126 | ||||
127 | inline void swap(QSharedDataPointer &other) Q_DECL_NOTHROWnoexcept | |||
128 | { qSwap(d, other.d); } | |||
129 | ||||
130 | protected: | |||
131 | T *clone(); | |||
132 | ||||
133 | private: | |||
134 | void detach_helper(); | |||
135 | ||||
136 | T *d; | |||
137 | }; | |||
138 | ||||
139 | template <class T> inline bool operator==(std::nullptr_t p1, const QSharedDataPointer<T> &p2) | |||
140 | { | |||
141 | Q_UNUSED(p1)(void)p1;; | |||
142 | return !p2; | |||
143 | } | |||
144 | ||||
145 | template <class T> inline bool operator==(const QSharedDataPointer<T> &p1, std::nullptr_t p2) | |||
146 | { | |||
147 | Q_UNUSED(p2)(void)p2;; | |||
148 | return !p1; | |||
149 | } | |||
150 | ||||
151 | template <class T> class QExplicitlySharedDataPointer | |||
152 | { | |||
153 | public: | |||
154 | typedef T Type; | |||
155 | typedef T *pointer; | |||
156 | ||||
157 | inline T &operator*() const { return *d; } | |||
158 | inline T *operator->() { return d; } | |||
159 | inline T *operator->() const { return d; } | |||
159 | inline T *operator->() const { return d; } | |||
| ||||
160 | inline T *data() const { return d; } | |||
161 | inline const T *constData() const { return d; } | |||
| ||||
161 | inline const T *constData() const { return d; } | |||
162 | inline T *take() { T *x = d; d = nullptr; return x; } | |||
163 | ||||
164 | inline void detach() { if (d && d->ref.load() != 1) detach_helper(); } | |||
165 | ||||
166 | inline void reset() | |||
167 | { | |||
168 | if(d && !d->ref.deref()) | |||
169 | delete d; | |||
170 | ||||
171 | d = nullptr; | |||
172 | } | |||
173 | ||||
174 | inline operator bool () const { return d != nullptr; } | |||
175 | ||||
176 | inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; } | |||
177 | inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; } | |||
178 | inline bool operator==(const T *ptr) const { return d == ptr; } | |||
179 | inline bool operator!=(const T *ptr) const { return d != ptr; } | |||
180 | ||||
181 | inline QExplicitlySharedDataPointer() { d = nullptr; } | |||
182 | inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; } | |||
183 | ||||
184 | explicit QExplicitlySharedDataPointer(T *data) Q_DECL_NOTHROWnoexcept; | |||
185 | inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } | |||
186 | ||||
187 | template<class X> | |||
188 | inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) | |||
189 | #ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST | |||
190 | : d(static_cast<T *>(o.data())) | |||
191 | #else | |||
192 | : d(o.data()) | |||
193 | #endif | |||
194 | { | |||
195 | if(d) | |||
196 | d->ref.ref(); | |||
197 | } | |||
198 | ||||
199 | inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) { | |||
200 | if (o.d != d) { | |||
201 | if (o.d) | |||
202 | o.d->ref.ref(); | |||
203 | T *old = d; | |||
204 | d = o.d; | |||
205 | if (old && !old->ref.deref()) | |||
206 | delete old; | |||
207 | } | |||
208 | return *this; | |||
209 | } | |||
210 | inline QExplicitlySharedDataPointer &operator=(T *o) { | |||
211 | if (o != d) { | |||
212 | if (o) | |||
213 | o->ref.ref(); | |||
214 | T *old = d; | |||
215 | d = o; | |||
216 | if (old && !old->ref.deref()) | |||
217 | delete old; | |||
218 | } | |||
219 | return *this; | |||
220 | } | |||
221 | #ifdef Q_COMPILER_RVALUE_REFS | |||
222 | inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) Q_DECL_NOTHROWnoexcept : d(o.d) { o.d = nullptr; } | |||
223 | inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) Q_DECL_NOTHROWnoexcept | |||
224 | { | |||
225 | QExplicitlySharedDataPointer moved(std::move(other)); | |||
226 | swap(moved); | |||
227 | return *this; | |||
228 | } | |||
229 | #endif | |||
230 | ||||
231 | inline bool operator!() const { return !d; } | |||
232 | ||||
233 | inline void swap(QExplicitlySharedDataPointer &other) Q_DECL_NOTHROWnoexcept | |||
234 | { qSwap(d, other.d); } | |||
235 | ||||
236 | protected: | |||
237 | T *clone(); | |||
238 | ||||
239 | private: | |||
240 | void detach_helper(); | |||
241 | ||||
242 | T *d; | |||
243 | }; | |||
244 | ||||
245 | template <class T> | |||
246 | Q_INLINE_TEMPLATEinline QSharedDataPointer<T>::QSharedDataPointer(T *adata) Q_DECL_NOTHROWnoexcept | |||
247 | : d(adata) | |||
248 | { if (d) d->ref.ref(); } | |||
249 | ||||
250 | template <class T> | |||
251 | Q_INLINE_TEMPLATEinline T *QSharedDataPointer<T>::clone() | |||
252 | { | |||
253 | return new T(*d); | |||
254 | } | |||
255 | ||||
256 | template <class T> | |||
257 | Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper() | |||
258 | { | |||
259 | T *x = clone(); | |||
260 | x->ref.ref(); | |||
261 | if (!d->ref.deref()) | |||
262 | delete d; | |||
263 | d = x; | |||
264 | } | |||
265 | ||||
266 | template <class T> | |||
267 | Q_INLINE_TEMPLATEinline T *QExplicitlySharedDataPointer<T>::clone() | |||
268 | { | |||
269 | return new T(*d); | |||
270 | } | |||
271 | ||||
272 | template <class T> | |||
273 | Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper() | |||
274 | { | |||
275 | T *x = clone(); | |||
276 | x->ref.ref(); | |||
277 | if (!d->ref.deref()) | |||
278 | delete d; | |||
279 | d = x; | |||
280 | } | |||
281 | ||||
282 | template <class T> | |||
283 | Q_INLINE_TEMPLATEinline QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) Q_DECL_NOTHROWnoexcept | |||
284 | : d(adata) | |||
285 | { if (d) d->ref.ref(); } | |||
286 | ||||
287 | template <class T> inline bool operator==(std::nullptr_t p1, const QExplicitlySharedDataPointer<T> &p2) | |||
288 | { | |||
289 | Q_UNUSED(p1)(void)p1;; | |||
290 | return !p2; | |||
291 | } | |||
292 | ||||
293 | template <class T> inline bool operator==(const QExplicitlySharedDataPointer<T> &p1, std::nullptr_t p2) | |||
294 | { | |||
295 | Q_UNUSED(p2)(void)p2;; | |||
296 | return !p1; | |||
297 | } | |||
298 | ||||
299 | template <class T> | |||
300 | Q_INLINE_TEMPLATEinline void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) | |||
301 | { p1.swap(p2); } | |||
302 | ||||
303 | template <class T> | |||
304 | Q_INLINE_TEMPLATEinline void qSwap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) | |||
305 | { p1.swap(p2); } | |||
306 | ||||
307 | QT_END_NAMESPACE | |||
308 | namespace std { | |||
309 | template <class T> | |||
310 | Q_INLINE_TEMPLATEinline void swap(QT_PREPEND_NAMESPACE(QSharedDataPointer)::QSharedDataPointer<T> &p1, QT_PREPEND_NAMESPACE(QSharedDataPointer)::QSharedDataPointer<T> &p2) | |||
311 | { p1.swap(p2); } | |||
312 | ||||
313 | template <class T> | |||
314 | Q_INLINE_TEMPLATEinline void swap(QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)::QExplicitlySharedDataPointer<T> &p1, QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)::QExplicitlySharedDataPointer<T> &p2) | |||
315 | { p1.swap(p2); } | |||
316 | } | |||
317 | QT_BEGIN_NAMESPACE | |||
318 | ||||
319 | template <class T> | |||
320 | Q_INLINE_TEMPLATEinline uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0) Q_DECL_NOTHROWnoexcept | |||
321 | { | |||
322 | return qHash(ptr.data(), seed); | |||
323 | } | |||
324 | template <class T> | |||
325 | Q_INLINE_TEMPLATEinline uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0) Q_DECL_NOTHROWnoexcept | |||
326 | { | |||
327 | return qHash(ptr.data(), seed); | |||
328 | } | |||
329 | ||||
330 | template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE)class QTypeInfo<QSharedDataPointer<T> > { public: enum { isSpecialized = true, isComplex = (((Q_MOVABLE_TYPE) & Q_PRIMITIVE_TYPE) == 0), isStatic = (((Q_MOVABLE_TYPE) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), isRelocatable = ! isStatic || ((Q_MOVABLE_TYPE) & Q_RELOCATABLE_TYPE), isLarge = (sizeof(QSharedDataPointer<T>)>sizeof(void*)), isPointer = false, isIntegral = std::is_integral< QSharedDataPointer <T> >::value, isDummy = (((Q_MOVABLE_TYPE) & Q_DUMMY_TYPE ) != 0), sizeOf = sizeof(QSharedDataPointer<T>) }; static inline const char *name() { return "QSharedDataPointer<T>" ; } }; | |||
331 | template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE)class QTypeInfo<QExplicitlySharedDataPointer<T> > { public: enum { isSpecialized = true, isComplex = (((Q_MOVABLE_TYPE ) & Q_PRIMITIVE_TYPE) == 0), isStatic = (((Q_MOVABLE_TYPE ) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), isRelocatable = !isStatic || ((Q_MOVABLE_TYPE) & Q_RELOCATABLE_TYPE), isLarge = (sizeof(QExplicitlySharedDataPointer<T>)>sizeof(void *)), isPointer = false, isIntegral = std::is_integral< QExplicitlySharedDataPointer <T> >::value, isDummy = (((Q_MOVABLE_TYPE) & Q_DUMMY_TYPE ) != 0), sizeOf = sizeof(QExplicitlySharedDataPointer<T> ) }; static inline const char *name() { return "QExplicitlySharedDataPointer<T>" ; } }; | |||
332 | ||||
333 | QT_END_NAMESPACE | |||
334 | ||||
335 | #endif // QSHAREDDATA_H |
File: | mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp |
Warning: | line 191, column 1 Potential leak of memory pointed to by 'item' |
Press '?' to see keyboard shortcuts
-Keyboard shortcuts:
1 | /* ============================================================ | |||
2 | * | |||
3 | * This file is a part of digiKam project | |||
4 | * https://www.digikam.org | |||
5 | * | |||
6 | * Date : 2005-03-27 | |||
7 | * Description : a digiKam image tool for fixing dots produced by | |||
8 | * hot/stuck/dead pixels from a CCD. | |||
9 | * | |||
10 | * Copyright (C) 2005-2019 by Gilles Caulier <caulier dot gilles at gmail dot com> | |||
11 | * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net> | |||
12 | * | |||
13 | * This program is free software; you can redistribute it | |||
14 | * and/or modify it under the terms of the GNU General | |||
15 | * Public License as published by the Free Software Foundation; | |||
16 | * either version 2, or (at your option) | |||
17 | * any later version. | |||
18 | * | |||
19 | * This program 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 | * ============================================================ */ | |||
25 | ||||
26 | #include "hotpixelstool.h" | |||
27 | ||||
28 | // Qt includes | |||
29 | ||||
30 | #include <QGridLayout> | |||
31 | #include <QLabel> | |||
32 | #include <QPolygon> | |||
33 | #include <QProgressBar> | |||
34 | #include <QPushButton> | |||
35 | #include <QIcon> | |||
36 | #include <QApplication> | |||
37 | ||||
38 | // KDE includes | |||
39 | ||||
40 | #include <klocalizedstring.h> | |||
41 | #include <ksharedconfig.h> | |||
42 | #include "kconfiggroup.h" | |||
43 | ||||
44 | // Local includes | |||
45 | ||||
46 | #include "blackframelistview.h" | |||
47 | #include "dcombobox.h" | |||
48 | #include "daboutdata.h" | |||
49 | #include "dimg.h" | |||
50 | #include "dimgfiltermanager.h" | |||
51 | #include "editortooliface.h" | |||
52 | #include "editortoolsettings.h" | |||
53 | #include "hotpixelfixer.h" | |||
54 | #include "imagedialog.h" | |||
55 | #include "imageiface.h" | |||
56 | #include "imageregionwidget.h" | |||
57 | ||||
58 | namespace DigikamEditorHotPixelsToolPlugin | |||
59 | { | |||
60 | ||||
61 | class Q_DECL_HIDDEN__attribute__((visibility("hidden"))) HotPixelsTool::Private | |||
62 | { | |||
63 | public: | |||
64 | ||||
65 | explicit Private() | |||
66 | : blackFrameButton(nullptr), | |||
67 | progressBar(nullptr), | |||
68 | filterMethodCombo(nullptr), | |||
69 | blackFrameListView(nullptr), | |||
70 | previewWidget(nullptr), | |||
71 | gboxSettings(nullptr) | |||
72 | { | |||
73 | } | |||
74 | ||||
75 | static const QString configGroupName; | |||
76 | static const QString configLastBlackFrameFileEntry; | |||
77 | static const QString configFilterMethodEntry; | |||
78 | ||||
79 | QPushButton* blackFrameButton; | |||
80 | QProgressBar* progressBar; | |||
81 | QList<HotPixel> hotPixelsList; | |||
82 | ||||
83 | QUrl blackFrameURL; | |||
84 | ||||
85 | DComboBox* filterMethodCombo; | |||
86 | ||||
87 | BlackFrameListView* blackFrameListView; | |||
88 | ImageRegionWidget* previewWidget; | |||
89 | EditorToolSettings* gboxSettings; | |||
90 | }; | |||
91 | ||||
92 | const QString HotPixelsTool::Private::configGroupName(QLatin1String("hotpixels Tool")); | |||
93 | const QString HotPixelsTool::Private::configLastBlackFrameFileEntry(QLatin1String("Last Black Frame File")); | |||
94 | const QString HotPixelsTool::Private::configFilterMethodEntry(QLatin1String("Filter Method")); | |||
95 | ||||
96 | // -------------------------------------------------------- | |||
97 | ||||
98 | HotPixelsTool::HotPixelsTool(QObject* const parent) | |||
99 | : EditorToolThreaded(parent), | |||
100 | d(new Private) | |||
101 | { | |||
102 | setObjectName(QLatin1String("hotpixels")); | |||
103 | setToolName(i18n("Hot Pixels")i18nd("digikam", "Hot Pixels")); | |||
104 | setToolIcon(QIcon::fromTheme(QLatin1String("hotpixels"))); | |||
105 | ||||
106 | // ------------------------------------------------------------- | |||
107 | ||||
108 | d->gboxSettings = new EditorToolSettings(nullptr); | |||
109 | d->gboxSettings->setButtons(EditorToolSettings::Default| | |||
110 | EditorToolSettings::Ok| | |||
111 | EditorToolSettings::Cancel| | |||
112 | EditorToolSettings::Try); | |||
113 | ||||
114 | QGridLayout* const grid = new QGridLayout(d->gboxSettings->plainPage()); | |||
115 | ||||
116 | QLabel* const filterMethodLabel = new QLabel(i18n("Filter:")i18nd("digikam", "Filter:"), d->gboxSettings->plainPage()); | |||
117 | d->filterMethodCombo = new DComboBox(d->gboxSettings->plainPage()); | |||
118 | d->filterMethodCombo->addItem(i18nc("average filter mode", "Average")i18ndc("digikam", "average filter mode", "Average")); | |||
119 | d->filterMethodCombo->addItem(i18nc("linear filter mode", "Linear")i18ndc("digikam", "linear filter mode", "Linear")); | |||
120 | d->filterMethodCombo->addItem(i18nc("quadratic filter mode", "Quadratic")i18ndc("digikam", "quadratic filter mode", "Quadratic")); | |||
121 | d->filterMethodCombo->addItem(i18nc("cubic filter mode", "Cubic")i18ndc("digikam", "cubic filter mode", "Cubic")); | |||
122 | d->filterMethodCombo->setDefaultIndex(HotPixelFixer::QUADRATIC_INTERPOLATION); | |||
123 | ||||
124 | d->blackFrameButton = new QPushButton(i18n("Black Frame...")i18nd("digikam", "Black Frame..."), d->gboxSettings->plainPage()); | |||
125 | d->blackFrameButton->setIcon(QIcon::fromTheme(QLatin1String("document-open"))); | |||
126 | d->blackFrameButton->setWhatsThis(i18n("Use this button to add a new black frame file which will "i18nd("digikam", "Use this button to add a new black frame file which will " "be used by the hot pixels removal filter.") | |||
127 | "be used by the hot pixels removal filter.")i18nd("digikam", "Use this button to add a new black frame file which will " "be used by the hot pixels removal filter.") ); | |||
128 | ||||
129 | d->blackFrameListView = new BlackFrameListView(d->gboxSettings->plainPage()); | |||
130 | ||||
131 | // ------------------------------------------------------------- | |||
132 | ||||
133 | const int spacing = d->gboxSettings->spacingHint(); | |||
134 | ||||
135 | grid->addWidget(filterMethodLabel, 0, 0, 1, 1); | |||
136 | grid->addWidget(d->filterMethodCombo, 0, 1, 1, 1); | |||
137 | grid->addWidget(d->blackFrameButton, 0, 2, 1, 1); | |||
138 | grid->addWidget(d->blackFrameListView, 1, 0, 2, 3); | |||
139 | grid->setRowStretch(3, 10); | |||
140 | grid->setContentsMargins(spacing, spacing, spacing, spacing); | |||
141 | grid->setSpacing(spacing); | |||
142 | ||||
143 | // ------------------------------------------------------------- | |||
144 | ||||
145 | d->previewWidget = new ImageRegionWidget; | |||
146 | ||||
147 | setToolSettings(d->gboxSettings); | |||
148 | setToolView(d->previewWidget); | |||
149 | setPreviewModeMask(PreviewToolBar::AllPreviewModes); | |||
150 | ||||
151 | // ------------------------------------------------------------- | |||
152 | ||||
153 | connect(d->filterMethodCombo, SIGNAL(activated(int))qFlagLocation("2""activated(int)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "153"), | |||
154 | this, SLOT(slotPreview())qFlagLocation("1""slotPreview()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "154")); | |||
155 | ||||
156 | connect(d->blackFrameButton, SIGNAL(clicked())qFlagLocation("2""clicked()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "156"), | |||
157 | this, SLOT(slotAddBlackFrame())qFlagLocation("1""slotAddBlackFrame()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "157")); | |||
158 | ||||
159 | connect(d->blackFrameListView, SIGNAL(signalBlackFrameSelected(QList<HotPixel>,QUrl))qFlagLocation("2""signalBlackFrameSelected(QList<HotPixel>,QUrl)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "159"), | |||
160 | this, SLOT(slotBlackFrame(QList<HotPixel>,QUrl))qFlagLocation("1""slotBlackFrame(QList<HotPixel>,QUrl)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "160")); | |||
161 | } | |||
162 | ||||
163 | HotPixelsTool::~HotPixelsTool() | |||
164 | { | |||
165 | delete d; | |||
166 | } | |||
167 | ||||
168 | void HotPixelsTool::registerFilter() | |||
169 | { | |||
170 | DImgFilterManager::instance()->addGenerator(new BasicDImgFilterGenerator<HotPixelFixer>()); | |||
171 | } | |||
172 | ||||
173 | void HotPixelsTool::readSettings() | |||
174 | { | |||
175 | KSharedConfig::Ptr config = KSharedConfig::openConfig(); | |||
176 | KConfigGroup group = config->group(d->configGroupName); | |||
177 | d->blackFrameURL = QUrl::fromLocalFile(group.readEntry(d->configLastBlackFrameFileEntry, QString())); | |||
178 | d->filterMethodCombo->setCurrentIndex(group.readEntry(d->configFilterMethodEntry, d->filterMethodCombo->defaultIndex())); | |||
179 | ||||
180 | if (d->blackFrameURL.isValid()) | |||
| ||||
181 | { | |||
182 | EditorToolIface::editorToolIface()->setToolStartProgress(i18n("Loading: ")i18nd("digikam", "Loading: ")); | |||
183 | BlackFrameListViewItem* item = new BlackFrameListViewItem(d->blackFrameListView, d->blackFrameURL); | |||
183 | BlackFrameListViewItem* const item = new BlackFrameListViewItem(d->blackFrameListView, d->blackFrameURL); | |||
184 | ||||
185 | connect(item, SIGNAL(signalLoadingProgress(float))qFlagLocation("2""signalLoadingProgress(float)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "185"), | |||
186 | this, SLOT(slotLoadingProgress(float))qFlagLocation("1""slotLoadingProgress(float)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "186")); | |||
187 | ||||
188 | connect(item, SIGNAL(signalLoadingComplete())qFlagLocation("2""signalLoadingComplete()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "188"), | |||
189 | this, SLOT(slotLoadingComplete())qFlagLocation("1""slotLoadingComplete()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "189")); | |||
190 | } | |||
191 | } | |||
| ||||
192 | ||||
193 | void HotPixelsTool::writeSettings() | |||
194 | { | |||
195 | KSharedConfig::Ptr config = KSharedConfig::openConfig(); | |||
196 | KConfigGroup group = config->group(d->configGroupName); | |||
197 | group.writeEntry(d->configLastBlackFrameFileEntry, d->blackFrameURL.url()); | |||
198 | group.writeEntry(d->configFilterMethodEntry, d->filterMethodCombo->currentIndex()); | |||
199 | group.sync(); | |||
200 | } | |||
201 | ||||
202 | void HotPixelsTool::slotLoadingProgress(float v) | |||
203 | { | |||
204 | EditorToolIface::editorToolIface()->setToolProgress((int)(v*100)); | |||
205 | } | |||
206 | ||||
207 | void HotPixelsTool::slotLoadingComplete() | |||
208 | { | |||
209 | EditorToolIface::editorToolIface()->setToolStopProgress(); | |||
210 | } | |||
211 | ||||
212 | void HotPixelsTool::slotResetSettings() | |||
213 | { | |||
214 | d->filterMethodCombo->blockSignals(true); | |||
215 | d->filterMethodCombo->slotReset(); | |||
216 | d->filterMethodCombo->blockSignals(false); | |||
217 | } | |||
218 | ||||
219 | void HotPixelsTool::slotAddBlackFrame() | |||
220 | { | |||
221 | QUrl url = ImageDialog::getImageURL(qApp(static_cast<QApplication *>(QCoreApplication::instance ()))->activeWindow(), d->blackFrameURL, i18n("Select Black Frame Image")i18nd("digikam", "Select Black Frame Image")); | |||
222 | ||||
223 | if (!url.isEmpty()) | |||
224 | { | |||
225 | // Load the selected file and insert into the list. | |||
226 | ||||
227 | d->blackFrameURL = url; | |||
228 | d->blackFrameListView->clear(); | |||
229 | BlackFrameListViewItem* item = new BlackFrameListViewItem(d->blackFrameListView, d->blackFrameURL); | |||
229 | BlackFrameListViewItem* const item = new BlackFrameListViewItem(d->blackFrameListView, d->blackFrameURL); | |||
230 | ||||
231 | connect(item, SIGNAL(signalLoadingProgress(float))qFlagLocation("2""signalLoadingProgress(float)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "231"), | |||
232 | this, SLOT(slotLoadingProgress(float))qFlagLocation("1""slotLoadingProgress(float)" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "232")); | |||
233 | ||||
234 | connect(item, SIGNAL(signalLoadingComplete())qFlagLocation("2""signalLoadingComplete()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "234"), | |||
235 | this, SLOT(slotLoadingComplete())qFlagLocation("1""slotLoadingComplete()" "\0" "/mnt/devel/GIT/6.x/core/dplugins/editor/enhance/hotpixels/hotpixelstool.cpp" ":" "235")); | |||
236 | } | |||
237 | } | |||
238 | ||||
239 | void HotPixelsTool::preparePreview() | |||
240 | { | |||
241 | DImg image = d->previewWidget->getOriginalRegionImage(); | |||
242 | int interpolationMethod = d->filterMethodCombo->currentIndex(); | |||
243 | ||||
244 | QList<HotPixel> hotPixelsRegion; | |||
245 | QRect area = d->previewWidget->getOriginalImageRegionToRender(); | |||
246 | ||||
247 | for (QList<HotPixel>::const_iterator it = d->hotPixelsList.constBegin() ; it != d->hotPixelsList.constEnd() ; ++it) | |||
248 | { | |||
249 | HotPixel hp = (*it); | |||
250 | ||||
251 | if (area.contains( hp.rect )) | |||
252 | { | |||
253 | hp.rect.moveTopLeft(QPoint( hp.rect.x()-area.x(), hp.rect.y()-area.y() )); | |||
254 | hotPixelsRegion.append(hp); | |||
255 | } | |||
256 | } | |||
257 | ||||
258 | setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(&image, this, hotPixelsRegion, interpolationMethod))); | |||
259 | } | |||
260 | ||||
261 | void HotPixelsTool::prepareFinal() | |||
262 | { | |||
263 | int interpolationMethod = d->filterMethodCombo->currentIndex(); | |||
264 | ||||
265 | ImageIface iface; | |||
266 | setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(iface.original(), this, d->hotPixelsList, interpolationMethod))); | |||
267 | } | |||
268 | ||||
269 | void HotPixelsTool::setPreviewImage() | |||
270 | { | |||
271 | d->previewWidget->setPreviewImage(filter()->getTargetImage()); | |||
272 | } | |||
273 | ||||
274 | void HotPixelsTool::setFinalImage() | |||
275 | { | |||
276 | ImageIface iface; | |||
277 | iface.setOriginal(i18n("Hot Pixels Correction")i18nd("digikam", "Hot Pixels Correction"), filter()->filterAction(), filter()->getTargetImage()); | |||
278 | } | |||
279 | ||||
280 | void HotPixelsTool::slotBlackFrame(const QList<HotPixel>& hpList, const QUrl& blackFrameURL) | |||
281 | { | |||
282 | d->blackFrameURL = blackFrameURL; | |||
283 | d->hotPixelsList = hpList; | |||
284 | ||||
285 | QPolygon pointList(d->hotPixelsList.size()); | |||
286 | QList <HotPixel>::const_iterator it; | |||
287 | int i = 0; | |||
288 | ||||
289 | for (it = d->hotPixelsList.constBegin() ; it != d->hotPixelsList.constEnd() ; ++it, ++i) | |||
290 | { | |||
291 | pointList.setPoint(i, (*it).rect.center()); | |||
292 | } | |||
293 | ||||
294 | d->previewWidget->setHighLightPoints(pointList); | |||
295 | ||||
296 | slotPreview(); | |||
297 | } | |||
298 | ||||
299 | } // namespace DigikamEditorHotPixelsToolPlugin | |||
247 | for (QList<HotPixel>::const_iterator it = d->hotPixelsList.constBegin() ; | |||
248 | it != d->hotPixelsList.constEnd() ; ++it) | |||
249 | { | |||
250 | HotPixel hp = (*it); | |||
251 | ||||
252 | if (area.contains( hp.rect )) | |||
253 | { | |||
254 | hp.rect.moveTopLeft(QPoint( hp.rect.x()-area.x(), hp.rect.y()-area.y() )); | |||
255 | hotPixelsRegion.append(hp); | |||
256 | } | |||
257 | } | |||
258 | ||||
259 | setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(&image, this, hotPixelsRegion, interpolationMethod))); | |||
260 | } | |||
261 | ||||
262 | void HotPixelsTool::prepareFinal() | |||
263 | { | |||
264 | int interpolationMethod = d->filterMethodCombo->currentIndex(); | |||
265 | ||||
266 | ImageIface iface; | |||
267 | setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(iface.original(), this, d->hotPixelsList, interpolationMethod))); | |||
268 | } | |||
269 | ||||
270 | void HotPixelsTool::setPreviewImage() | |||
271 | { | |||
272 | d->previewWidget->setPreviewImage(filter()->getTargetImage()); | |||
273 | } | |||
274 | ||||
275 | void HotPixelsTool::setFinalImage() | |||
276 | { | |||
277 | ImageIface iface; | |||
278 | iface.setOriginal(i18n("Hot Pixels Correction")i18nd("digikam", "Hot Pixels Correction"), filter()->filterAction(), filter()->getTargetImage()); | |||
279 | } | |||
280 | ||||
281 | void HotPixelsTool::slotBlackFrame(const QList<HotPixel>& hpList, const QUrl& blackFrameURL) | |||
282 | { | |||
283 | d->blackFrameURL = blackFrameURL; | |||
284 | d->hotPixelsList = hpList; | |||
285 | ||||
286 | QPolygon pointList(d->hotPixelsList.size()); | |||
287 | QList <HotPixel>::const_iterator it; | |||
288 | int i = 0; | |||
289 | ||||
290 | for (it = d->hotPixelsList.constBegin() ; it != d->hotPixelsList.constEnd() ; ++it, ++i) | |||
291 | { | |||
292 | pointList.setPoint(i, (*it).rect.center()); | |||
293 | } | |||
294 | ||||
295 | d->previewWidget->setHighLightPoints(pointList); | |||
296 | ||||
297 | slotPreview(); | |||
298 | } | |||
299 | ||||
300 | } // namespace DigikamEditorHotPixelsToolPlugin |