Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zxing-cpp/example/ZXingQtReader.h @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * Copyright 2020 Axel Waggershauser | |
| 3 */ | |
| 4 // SPDX-License-Identifier: Apache-2.0 | |
| 5 | |
| 6 #pragma once | |
| 7 | |
| 8 #include "ReadBarcode.h" | |
| 9 | |
| 10 #include <QImage> | |
| 11 #include <QDebug> | |
| 12 #include <QMetaType> | |
| 13 #include <QScopeGuard> | |
| 14 | |
| 15 #ifdef QT_MULTIMEDIA_LIB | |
| 16 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 17 #include <QAbstractVideoFilter> | |
| 18 #else | |
| 19 #include <QVideoFrame> | |
| 20 #include <QVideoSink> | |
| 21 #endif | |
| 22 #include <QElapsedTimer> | |
| 23 #endif | |
| 24 | |
| 25 // This is some sample code to start a discussion about how a minimal and header-only Qt wrapper/helper could look like. | |
| 26 | |
| 27 namespace ZXingQt { | |
| 28 | |
| 29 Q_NAMESPACE | |
| 30 | |
| 31 //TODO: find a better way to export these enums to QML than to duplicate their definition | |
| 32 // #ifdef Q_MOC_RUN produces meta information in the moc output but it does end up working in qml | |
| 33 #ifdef QT_QML_LIB | |
| 34 enum class BarcodeFormat | |
| 35 { | |
| 36 None = 0, ///< Used as a return value if no valid barcode has been detected | |
| 37 Aztec = (1 << 0), ///< Aztec | |
| 38 Codabar = (1 << 1), ///< Codabar | |
| 39 Code39 = (1 << 2), ///< Code39 | |
| 40 Code93 = (1 << 3), ///< Code93 | |
| 41 Code128 = (1 << 4), ///< Code128 | |
| 42 DataBar = (1 << 5), ///< GS1 DataBar, formerly known as RSS 14 | |
| 43 DataBarExpanded = (1 << 6), ///< GS1 DataBar Expanded, formerly known as RSS EXPANDED | |
| 44 DataMatrix = (1 << 7), ///< DataMatrix | |
| 45 EAN8 = (1 << 8), ///< EAN-8 | |
| 46 EAN13 = (1 << 9), ///< EAN-13 | |
| 47 ITF = (1 << 10), ///< ITF (Interleaved Two of Five) | |
| 48 MaxiCode = (1 << 11), ///< MaxiCode | |
| 49 PDF417 = (1 << 12), ///< PDF417 or | |
| 50 QRCode = (1 << 13), ///< QR Code | |
| 51 UPCA = (1 << 14), ///< UPC-A | |
| 52 UPCE = (1 << 15), ///< UPC-E | |
| 53 MicroQRCode = (1 << 16), ///< Micro QR Code | |
| 54 RMQRCode = (1 << 17), ///< Rectangular Micro QR Code | |
| 55 DXFilmEdge = (1 << 18), ///< DX Film Edge Barcode | |
| 56 DataBarLimited = (1 << 19), ///< GS1 DataBar Limited | |
| 57 | |
| 58 LinearCodes = Codabar | Code39 | Code93 | Code128 | EAN8 | EAN13 | ITF | DataBar | DataBarExpanded | DataBarLimited | DXFilmEdge | UPCA | UPCE, | |
| 59 MatrixCodes = Aztec | DataMatrix | MaxiCode | PDF417 | QRCode | MicroQRCode | RMQRCode, | |
| 60 }; | |
| 61 | |
| 62 enum class ContentType { Text, Binary, Mixed, GS1, ISO15434, UnknownECI }; | |
| 63 | |
| 64 enum class TextMode { Plain, ECI, HRI, Hex, Escaped }; | |
| 65 | |
| 66 #else | |
| 67 using ZXing::BarcodeFormat; | |
| 68 using ZXing::ContentType; | |
| 69 using ZXing::TextMode; | |
| 70 #endif | |
| 71 | |
| 72 using ZXing::ReaderOptions; | |
| 73 using ZXing::Binarizer; | |
| 74 using ZXing::BarcodeFormats; | |
| 75 | |
| 76 Q_ENUM_NS(BarcodeFormat) | |
| 77 Q_ENUM_NS(ContentType) | |
| 78 Q_ENUM_NS(TextMode) | |
| 79 | |
| 80 template<typename T, typename = decltype(ZXing::ToString(T()))> | |
| 81 QDebug operator<<(QDebug dbg, const T& v) | |
| 82 { | |
| 83 return dbg.noquote() << QString::fromStdString(ToString(v)); | |
| 84 } | |
| 85 | |
| 86 class Position : public ZXing::Quadrilateral<QPoint> | |
| 87 { | |
| 88 Q_GADGET | |
| 89 | |
| 90 Q_PROPERTY(QPoint topLeft READ topLeft) | |
| 91 Q_PROPERTY(QPoint topRight READ topRight) | |
| 92 Q_PROPERTY(QPoint bottomRight READ bottomRight) | |
| 93 Q_PROPERTY(QPoint bottomLeft READ bottomLeft) | |
| 94 | |
| 95 using Base = ZXing::Quadrilateral<QPoint>; | |
| 96 | |
| 97 public: | |
| 98 using Base::Base; | |
| 99 }; | |
| 100 | |
| 101 class Barcode : private ZXing::Barcode | |
| 102 { | |
| 103 Q_GADGET | |
| 104 | |
| 105 Q_PROPERTY(BarcodeFormat format READ format) | |
| 106 Q_PROPERTY(QString formatName READ formatName) | |
| 107 Q_PROPERTY(QString text READ text) | |
| 108 Q_PROPERTY(QByteArray bytes READ bytes) | |
| 109 Q_PROPERTY(bool isValid READ isValid) | |
| 110 Q_PROPERTY(ContentType contentType READ contentType) | |
| 111 Q_PROPERTY(QString contentTypeName READ contentTypeName) | |
| 112 Q_PROPERTY(Position position READ position) | |
| 113 | |
| 114 QString _text; | |
| 115 QByteArray _bytes; | |
| 116 Position _position; | |
| 117 | |
| 118 public: | |
| 119 Barcode() = default; // required for qmetatype machinery | |
| 120 | |
| 121 explicit Barcode(ZXing::Barcode&& r) : ZXing::Barcode(std::move(r)) { | |
| 122 _text = QString::fromStdString(ZXing::Barcode::text()); | |
| 123 _bytes = QByteArray(reinterpret_cast<const char*>(ZXing::Barcode::bytes().data()), Size(ZXing::Barcode::bytes())); | |
| 124 auto& pos = ZXing::Barcode::position(); | |
| 125 auto qp = [&pos](int i) { return QPoint(pos[i].x, pos[i].y); }; | |
| 126 _position = {qp(0), qp(1), qp(2), qp(3)}; | |
| 127 } | |
| 128 | |
| 129 using ZXing::Barcode::isValid; | |
| 130 | |
| 131 BarcodeFormat format() const { return static_cast<BarcodeFormat>(ZXing::Barcode::format()); } | |
| 132 ContentType contentType() const { return static_cast<ContentType>(ZXing::Barcode::contentType()); } | |
| 133 QString formatName() const { return QString::fromStdString(ZXing::ToString(ZXing::Barcode::format())); } | |
| 134 QString contentTypeName() const { return QString::fromStdString(ZXing::ToString(ZXing::Barcode::contentType())); } | |
| 135 const QString& text() const { return _text; } | |
| 136 const QByteArray& bytes() const { return _bytes; } | |
| 137 const Position& position() const { return _position; } | |
| 138 }; | |
| 139 | |
| 140 inline QList<Barcode> ZXBarcodesToQBarcodes(ZXing::Barcodes&& zxres) | |
| 141 { | |
| 142 QList<Barcode> res; | |
| 143 for (auto&& r : zxres) | |
| 144 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 145 res.push_back(Barcode(std::move(r))); | |
| 146 #else | |
| 147 res.emplace_back(std::move(r)); | |
| 148 #endif | |
| 149 return res; | |
| 150 } | |
| 151 | |
| 152 inline QList<Barcode> ReadBarcodes(const QImage& img, const ReaderOptions& opts = {}) | |
| 153 { | |
| 154 using namespace ZXing; | |
| 155 | |
| 156 auto ImgFmtFromQImg = [](const QImage& img) { | |
| 157 switch (img.format()) { | |
| 158 case QImage::Format_ARGB32: | |
| 159 case QImage::Format_RGB32: | |
| 160 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN | |
| 161 return ImageFormat::BGRA; | |
| 162 #else | |
| 163 return ImageFormat::ARGB; | |
| 164 #endif | |
| 165 case QImage::Format_RGB888: return ImageFormat::RGB; | |
| 166 case QImage::Format_RGBX8888: | |
| 167 case QImage::Format_RGBA8888: return ImageFormat::RGBA; | |
| 168 case QImage::Format_Grayscale8: return ImageFormat::Lum; | |
| 169 default: return ImageFormat::None; | |
| 170 } | |
| 171 }; | |
| 172 | |
| 173 auto exec = [&](const QImage& img) { | |
| 174 return ZXBarcodesToQBarcodes(ZXing::ReadBarcodes( | |
| 175 {img.bits(), img.width(), img.height(), ImgFmtFromQImg(img), static_cast<int>(img.bytesPerLine())}, opts)); | |
| 176 }; | |
| 177 | |
| 178 return ImgFmtFromQImg(img) == ImageFormat::None ? exec(img.convertToFormat(QImage::Format_Grayscale8)) : exec(img); | |
| 179 } | |
| 180 | |
| 181 inline Barcode ReadBarcode(const QImage& img, const ReaderOptions& opts = {}) | |
| 182 { | |
| 183 auto res = ReadBarcodes(img, ReaderOptions(opts).setMaxNumberOfSymbols(1)); | |
| 184 return !res.isEmpty() ? res.takeFirst() : Barcode(); | |
| 185 } | |
| 186 | |
| 187 #ifdef QT_MULTIMEDIA_LIB | |
| 188 inline QList<Barcode> ReadBarcodes(const QVideoFrame& frame, const ReaderOptions& opts = {}) | |
| 189 { | |
| 190 using namespace ZXing; | |
| 191 | |
| 192 ImageFormat fmt = ImageFormat::None; | |
| 193 int pixStride = 0; | |
| 194 int pixOffset = 0; | |
| 195 | |
| 196 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 197 #define FORMAT(F5, F6) QVideoFrame::Format_##F5 | |
| 198 #define FIRST_PLANE | |
| 199 #else | |
| 200 #define FORMAT(F5, F6) QVideoFrameFormat::Format_##F6 | |
| 201 #define FIRST_PLANE 0 | |
| 202 #endif | |
| 203 | |
| 204 switch (frame.pixelFormat()) { | |
| 205 case FORMAT(ARGB32, ARGB8888): | |
| 206 case FORMAT(ARGB32_Premultiplied, ARGB8888_Premultiplied): | |
| 207 case FORMAT(RGB32, RGBX8888): | |
| 208 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN | |
| 209 fmt = ImageFormat::BGRA; | |
| 210 #else | |
| 211 fmt = ImageFormat::ARGB; | |
| 212 #endif | |
| 213 break; | |
| 214 | |
| 215 case FORMAT(BGRA32, BGRA8888): | |
| 216 case FORMAT(BGRA32_Premultiplied, BGRA8888_Premultiplied): | |
| 217 case FORMAT(BGR32, BGRX8888): | |
| 218 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN | |
| 219 fmt = ImageFormat::RGBA; | |
| 220 #else | |
| 221 fmt = ImageFormat::ABGR; | |
| 222 #endif | |
| 223 break; | |
| 224 | |
| 225 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 226 case QVideoFrame::Format_RGB24: fmt = ImageFormat::RGB; break; | |
| 227 case QVideoFrame::Format_BGR24: fmt = ImageFormat::BGR; break; | |
| 228 case QVideoFrame::Format_YUV444: fmt = ImageFormat::Lum, pixStride = 3; break; | |
| 229 #else | |
| 230 case QVideoFrameFormat::Format_P010: | |
| 231 case QVideoFrameFormat::Format_P016: fmt = ImageFormat::Lum, pixStride = 1; break; | |
| 232 #endif | |
| 233 | |
| 234 case FORMAT(AYUV444, AYUV): | |
| 235 case FORMAT(AYUV444_Premultiplied, AYUV_Premultiplied): | |
| 236 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN | |
| 237 fmt = ImageFormat::Lum, pixStride = 4, pixOffset = 3; | |
| 238 #else | |
| 239 fmt = ImageFormat::Lum, pixStride = 4, pixOffset = 2; | |
| 240 #endif | |
| 241 break; | |
| 242 | |
| 243 case FORMAT(YUV420P, YUV420P): | |
| 244 case FORMAT(NV12, NV12): | |
| 245 case FORMAT(NV21, NV21): | |
| 246 case FORMAT(IMC1, IMC1): | |
| 247 case FORMAT(IMC2, IMC2): | |
| 248 case FORMAT(IMC3, IMC3): | |
| 249 case FORMAT(IMC4, IMC4): | |
| 250 case FORMAT(YV12, YV12): fmt = ImageFormat::Lum; break; | |
| 251 case FORMAT(UYVY, UYVY): fmt = ImageFormat::Lum, pixStride = 2, pixOffset = 1; break; | |
| 252 case FORMAT(YUYV, YUYV): fmt = ImageFormat::Lum, pixStride = 2; break; | |
| 253 | |
| 254 case FORMAT(Y8, Y8): fmt = ImageFormat::Lum; break; | |
| 255 case FORMAT(Y16, Y16): fmt = ImageFormat::Lum, pixStride = 2, pixOffset = 1; break; | |
| 256 | |
| 257 #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) | |
| 258 case FORMAT(ABGR32, ABGR8888): | |
| 259 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN | |
| 260 fmt = ImageFormat::RGBA; | |
| 261 #else | |
| 262 fmt = ImageFormat::ABGR; | |
| 263 #endif | |
| 264 break; | |
| 265 #endif | |
| 266 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) | |
| 267 case FORMAT(YUV422P, YUV422P): fmt = ImageFormat::Lum; break; | |
| 268 #endif | |
| 269 default: break; | |
| 270 } | |
| 271 | |
| 272 if (fmt != ImageFormat::None) { | |
| 273 auto img = frame; // shallow copy just get access to non-const map() function | |
| 274 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 275 if (!img.isValid() || !img.map(QAbstractVideoBuffer::ReadOnly)){ | |
| 276 #else | |
| 277 if (!img.isValid() || !img.map(QVideoFrame::ReadOnly)){ | |
| 278 #endif | |
| 279 qWarning() << "invalid QVideoFrame: could not map memory"; | |
| 280 return {}; | |
| 281 } | |
| 282 QScopeGuard unmap([&] { img.unmap(); }); | |
| 283 | |
| 284 return ZXBarcodesToQBarcodes(ZXing::ReadBarcodes( | |
| 285 {img.bits(FIRST_PLANE) + pixOffset, img.width(), img.height(), fmt, img.bytesPerLine(FIRST_PLANE), pixStride}, opts)); | |
| 286 } | |
| 287 else { | |
| 288 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 289 if (QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat()) != QImage::Format_Invalid) { | |
| 290 qWarning() << "unsupported QVideoFrame::pixelFormat"; | |
| 291 return {}; | |
| 292 } | |
| 293 auto qimg = frame.image(); | |
| 294 #else | |
| 295 auto qimg = frame.toImage(); | |
| 296 #endif | |
| 297 if (qimg.format() != QImage::Format_Invalid) | |
| 298 return ReadBarcodes(qimg, opts); | |
| 299 qWarning() << "failed to convert QVideoFrame to QImage"; | |
| 300 return {}; | |
| 301 } | |
| 302 } | |
| 303 | |
| 304 inline Barcode ReadBarcode(const QVideoFrame& frame, const ReaderOptions& opts = {}) | |
| 305 { | |
| 306 auto res = ReadBarcodes(frame, ReaderOptions(opts).setMaxNumberOfSymbols(1)); | |
| 307 return !res.isEmpty() ? res.takeFirst() : Barcode(); | |
| 308 } | |
| 309 | |
| 310 #define ZQ_PROPERTY(Type, name, setter) \ | |
| 311 public: \ | |
| 312 Q_PROPERTY(Type name READ name WRITE setter NOTIFY name##Changed) \ | |
| 313 Type name() const noexcept { return ReaderOptions::name(); } \ | |
| 314 Q_SLOT void setter(const Type& newVal) \ | |
| 315 { \ | |
| 316 if (name() != newVal) { \ | |
| 317 ReaderOptions::setter(newVal); \ | |
| 318 emit name##Changed(); \ | |
| 319 } \ | |
| 320 } \ | |
| 321 Q_SIGNAL void name##Changed(); | |
| 322 | |
| 323 | |
| 324 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 325 class BarcodeReader : public QAbstractVideoFilter, private ReaderOptions | |
| 326 #else | |
| 327 class BarcodeReader : public QObject, private ReaderOptions | |
| 328 #endif | |
| 329 { | |
| 330 Q_OBJECT | |
| 331 | |
| 332 public: | |
| 333 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 334 BarcodeReader(QObject* parent = nullptr) : QAbstractVideoFilter(parent) {} | |
| 335 #else | |
| 336 BarcodeReader(QObject* parent = nullptr) : QObject(parent) {} | |
| 337 #endif | |
| 338 | |
| 339 // TODO: find out how to properly expose QFlags to QML | |
| 340 // simply using ZQ_PROPERTY(BarcodeFormats, formats, setFormats) | |
| 341 // results in the runtime error "can't assign int to formats" | |
| 342 Q_PROPERTY(int formats READ formats WRITE setFormats NOTIFY formatsChanged) | |
| 343 int formats() const noexcept | |
| 344 { | |
| 345 auto fmts = ReaderOptions::formats(); | |
| 346 return *reinterpret_cast<int*>(&fmts); | |
| 347 } | |
| 348 Q_SLOT void setFormats(int newVal) | |
| 349 { | |
| 350 if (formats() != newVal) { | |
| 351 ReaderOptions::setFormats(static_cast<ZXing::BarcodeFormat>(newVal)); | |
| 352 emit formatsChanged(); | |
| 353 qDebug() << ReaderOptions::formats(); | |
| 354 } | |
| 355 } | |
| 356 Q_SIGNAL void formatsChanged(); | |
| 357 | |
| 358 Q_PROPERTY(TextMode textMode READ textMode WRITE setTextMode NOTIFY textModeChanged) | |
| 359 TextMode textMode() const noexcept { return static_cast<TextMode>(ReaderOptions::textMode()); } | |
| 360 Q_SLOT void setTextMode(TextMode newVal) | |
| 361 { | |
| 362 if (textMode() != newVal) { | |
| 363 ReaderOptions::setTextMode(static_cast<ZXing::TextMode>(newVal)); | |
| 364 emit textModeChanged(); | |
| 365 } | |
| 366 } | |
| 367 Q_SIGNAL void textModeChanged(); | |
| 368 | |
| 369 ZQ_PROPERTY(bool, tryRotate, setTryRotate) | |
| 370 ZQ_PROPERTY(bool, tryHarder, setTryHarder) | |
| 371 ZQ_PROPERTY(bool, tryInvert, setTryInvert) | |
| 372 ZQ_PROPERTY(bool, tryDownscale, setTryDownscale) | |
| 373 ZQ_PROPERTY(bool, isPure, setIsPure) | |
| 374 | |
| 375 // For debugging/development | |
| 376 int runTime = 0; | |
| 377 Q_PROPERTY(int runTime MEMBER runTime) | |
| 378 | |
| 379 public slots: | |
| 380 ZXingQt::Barcode process(const QVideoFrame& image) | |
| 381 { | |
| 382 QElapsedTimer t; | |
| 383 t.start(); | |
| 384 | |
| 385 auto res = ReadBarcode(image, *this); | |
| 386 | |
| 387 runTime = t.elapsed(); | |
| 388 | |
| 389 if (res.isValid()) | |
| 390 emit foundBarcode(res); | |
| 391 else | |
| 392 emit failedRead(); | |
| 393 return res; | |
| 394 } | |
| 395 | |
| 396 signals: | |
| 397 void failedRead(); | |
| 398 void foundBarcode(ZXingQt::Barcode barcode); | |
| 399 | |
| 400 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 401 public: | |
| 402 QVideoFilterRunnable *createFilterRunnable() override; | |
| 403 #else | |
| 404 private: | |
| 405 QVideoSink *_sink = nullptr; | |
| 406 | |
| 407 public: | |
| 408 void setVideoSink(QVideoSink* sink) { | |
| 409 if (_sink == sink) | |
| 410 return; | |
| 411 | |
| 412 if (_sink) | |
| 413 disconnect(_sink, nullptr, this, nullptr); | |
| 414 | |
| 415 _sink = sink; | |
| 416 connect(_sink, &QVideoSink::videoFrameChanged, this, &BarcodeReader::process); | |
| 417 } | |
| 418 Q_PROPERTY(QVideoSink* videoSink MEMBER _sink WRITE setVideoSink) | |
| 419 #endif | |
| 420 | |
| 421 }; | |
| 422 | |
| 423 #undef ZX_PROPERTY | |
| 424 | |
| 425 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
| 426 class VideoFilterRunnable : public QVideoFilterRunnable | |
| 427 { | |
| 428 BarcodeReader* _filter = nullptr; | |
| 429 | |
| 430 public: | |
| 431 explicit VideoFilterRunnable(BarcodeReader* filter) : _filter(filter) {} | |
| 432 | |
| 433 QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat& /*surfaceFormat*/, RunFlags /*flags*/) override | |
| 434 { | |
| 435 _filter->process(*input); | |
| 436 return *input; | |
| 437 } | |
| 438 }; | |
| 439 | |
| 440 inline QVideoFilterRunnable* BarcodeReader::createFilterRunnable() | |
| 441 { | |
| 442 return new VideoFilterRunnable(this); | |
| 443 } | |
| 444 #endif | |
| 445 | |
| 446 #endif // QT_MULTIMEDIA_LIB | |
| 447 | |
| 448 } // namespace ZXingQt | |
| 449 | |
| 450 | |
| 451 Q_DECLARE_METATYPE(ZXingQt::Position) | |
| 452 Q_DECLARE_METATYPE(ZXingQt::Barcode) | |
| 453 | |
| 454 #ifdef QT_QML_LIB | |
| 455 | |
| 456 #include <QQmlEngine> | |
| 457 | |
| 458 namespace ZXingQt { | |
| 459 | |
| 460 inline void registerQmlAndMetaTypes() | |
| 461 { | |
| 462 qRegisterMetaType<ZXingQt::BarcodeFormat>("BarcodeFormat"); | |
| 463 qRegisterMetaType<ZXingQt::ContentType>("ContentType"); | |
| 464 qRegisterMetaType<ZXingQt::TextMode>("TextMode"); | |
| 465 | |
| 466 // supposedly the Q_DECLARE_METATYPE should be used with the overload without a custom name | |
| 467 // but then the qml side complains about "unregistered type" | |
| 468 qRegisterMetaType<ZXingQt::Position>("Position"); | |
| 469 qRegisterMetaType<ZXingQt::Barcode>("Barcode"); | |
| 470 | |
| 471 qmlRegisterUncreatableMetaObject( | |
| 472 ZXingQt::staticMetaObject, "ZXing", 1, 0, "ZXing", "Access to enums & flags only"); | |
| 473 qmlRegisterType<ZXingQt::BarcodeReader>("ZXing", 1, 0, "BarcodeReader"); | |
| 474 } | |
| 475 | |
| 476 } // namespace ZXingQt | |
| 477 | |
| 478 #endif // QT_QML_LIB |
