summaryrefslogtreecommitdiffstats
path: root/qt
diff options
context:
space:
mode:
Diffstat (limited to 'qt')
-rw-r--r--qt/Makefile.am.inc19
-rw-r--r--qt/QZBar.cpp364
-rw-r--r--qt/QZBarThread.cpp358
-rw-r--r--qt/QZBarThread.h192
4 files changed, 933 insertions, 0 deletions
diff --git a/qt/Makefile.am.inc b/qt/Makefile.am.inc
new file mode 100644
index 0000000..fba4fdf
--- /dev/null
+++ b/qt/Makefile.am.inc
@@ -0,0 +1,19 @@
+lib_LTLIBRARIES += qt/libzbarqt.la
+qt_libzbarqt_la_CPPFLAGS = -Iqt $(QT_CFLAGS) $(AM_CPPFLAGS)
+qt_libzbarqt_la_LDFLAGS = -version-info $(ZQT_LIB_VERSION) $(AM_LDFLAGS) $(LIBQT_EXTRA_LDFLAGS)
+qt_libzbarqt_la_LIBADD = $(QT_LIBS) zbar/libzbar.la $(AM_LIBADD)
+
+qt_libzbarqt_la_SOURCES = qt/QZBar.cpp qt/QZBarThread.h qt/QZBarThread.cpp
+nodist_qt_libzbarqt_la_SOURCES = qt/moc_QZBar.cpp qt/moc_QZBarThread.cpp
+BUILT_SOURCES += $(nodist_qt_libzbarqt_la_SOURCES)
+DISTCLEANFILES += $(nodist_qt_libzbarqt_la_SOURCES)
+
+clean-local:
+ -rm -vf qt/moc_*.cpp
+
+qt/moc_%.cpp: qt/%.h
+ $(MOC) $(qt_libzbarqt_la_CPPFLAGS) $< -o $@
+
+qt/moc_%.cpp: include/zbar/%.h
+ $(mkdir_p) qt
+ $(MOC) $(qt_libzbarqt_la_CPPFLAGS) $< -o $@
diff --git a/qt/QZBar.cpp b/qt/QZBar.cpp
new file mode 100644
index 0000000..14bdc56
--- /dev/null
+++ b/qt/QZBar.cpp
@@ -0,0 +1,364 @@
+//------------------------------------------------------------------------
+// Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+//
+// This file is part of the ZBar Bar Code Reader.
+//
+// The ZBar Bar Code Reader is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser Public License as
+// published by the Free Software Foundation; either version 2.1 of
+// the License, or (at your option) any later version.
+//
+// The ZBar Bar Code Reader is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser Public License for more details.
+//
+// You should have received a copy of the GNU Lesser Public License
+// along with the ZBar Bar Code Reader; if not, write to the Free
+// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301 USA
+//
+// http://sourceforge.net/projects/zbar
+//------------------------------------------------------------------------
+
+#include <QX11Info>
+#include <qevent.h>
+#include <qurl.h>
+#include <zbar/QZBar.h>
+#include "QZBarThread.h"
+
+using namespace zbar;
+
+QZBar::QZBar(QWidget *parent, int verbosity)
+ : QWidget(parent), thread(NULL), _videoDevice(), _videoEnabled(false),
+ _attached(false)
+{
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ setAttribute(Qt::WA_PaintOnScreen);
+#if QT_VERSION >= 0x040400
+ setAttribute(Qt::WA_NativeWindow);
+ setAttribute(Qt::WA_DontCreateNativeAncestors);
+#endif
+
+ QSizePolicy sizing(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sizing.setHeightForWidth(true);
+ setSizePolicy(sizing);
+
+ thread = new QZBarThread(verbosity);
+ if (testAttribute(Qt::WA_WState_Created)) {
+#if QT_VERSION >= 0x050000
+ thread->window.attach(QX11Info::display(), winId());
+#else
+ thread->window.attach(x11Info().display(), winId());
+#endif
+ _attached = 1;
+ }
+ connect(thread, SIGNAL(videoOpened(bool)), this, SIGNAL(videoOpened(bool)));
+ connect(this, SIGNAL(videoOpened(bool)), this, SLOT(sizeChange()));
+ connect(thread, SIGNAL(update()), this, SLOT(update()));
+ connect(thread, SIGNAL(decoded(int, const QString &)), this,
+ SIGNAL(decoded(int, const QString &)));
+ connect(thread, SIGNAL(decodedText(const QString &)), this,
+ SIGNAL(decodedText(const QString &)));
+ thread->start();
+}
+
+QZBar::~QZBar()
+{
+ if (thread) {
+ thread->pushEvent(new QEvent((QEvent::Type)QZBarThread::Exit));
+ thread->wait();
+ delete thread;
+ thread = NULL;
+ }
+}
+
+QPaintEngine *QZBar::paintEngine() const
+{
+ return (NULL);
+}
+
+QString QZBar::videoDevice() const
+{
+ return (_videoDevice);
+}
+
+void QZBar::setVideoDevice(const QString &videoDevice)
+{
+ if (!thread)
+ return;
+ if (_videoDevice != videoDevice) {
+ _videoDevice = videoDevice;
+ _videoEnabled = _attached && !videoDevice.isEmpty();
+ if (_attached)
+ thread->pushEvent(new QZBarThread::VideoDeviceEvent(videoDevice));
+ }
+}
+
+int QZBar::get_controls(int index, char **name, char **group,
+ enum ControlType *type, int *min, int *max, int *def,
+ int *step)
+{
+ if (!thread)
+ return 0;
+
+ return thread->get_controls(index, name, group, type, min, max, def, step);
+}
+
+void QZBar::request_size(unsigned width, unsigned height, bool trigger)
+{
+ if (!thread)
+ return;
+
+ thread->request_size(width, height);
+ if (trigger)
+ thread->pushEvent(new QEvent((QEvent::Type)QZBarThread::ReOpen));
+}
+
+int QZBar::get_resolution(int index, unsigned &width, unsigned &height,
+ float &max_fps)
+{
+ if (!thread)
+ return 0;
+
+ return thread->get_resolution(index, width, height, max_fps);
+}
+
+unsigned QZBar::videoWidth()
+{
+ if (!thread)
+ return 0;
+
+ return thread->reqWidth;
+}
+
+unsigned QZBar::videoHeight()
+{
+ if (!thread)
+ return 0;
+
+ return thread->reqHeight;
+}
+
+QVector<QPair<int, QString> > QZBar::get_menu(int index)
+{
+ if (!thread) {
+ QVector<QPair<int, QString> > empty;
+ return empty;
+ }
+
+ return thread->get_menu(index);
+}
+
+int QZBar::set_control(char *name, bool value)
+{
+ if (!thread)
+ return 0;
+
+ return thread->set_control(name, value);
+}
+
+int QZBar::set_control(char *name, int value)
+{
+ if (!thread)
+ return 0;
+
+ return thread->set_control(name, value);
+}
+
+int QZBar::get_control(char *name, bool *value)
+{
+ if (!thread)
+ return 0;
+
+ return thread->get_control(name, value);
+}
+
+int QZBar::get_control(char *name, int *value)
+{
+ if (!thread)
+ return 0;
+
+ return thread->get_control(name, value);
+}
+
+int QZBar::set_config(std::string cfgstr)
+{
+ if (!thread)
+ return 0;
+
+ return thread->set_config(cfgstr);
+}
+
+int QZBar::set_config(zbar_symbol_type_t symbology, zbar_config_t config,
+ int value)
+{
+ if (!thread)
+ return 0;
+
+ return thread->set_config(symbology, config, value);
+}
+
+int QZBar::get_config(zbar_symbol_type_t symbology, zbar_config_t config,
+ int &value)
+{
+ if (!thread)
+ return 0;
+
+ return thread->get_config(symbology, config, value);
+}
+
+int QZBar::request_dbus(bool enabled)
+{
+ if (!thread)
+ return 0;
+
+ return thread->request_dbus(enabled);
+}
+
+bool QZBar::isVideoEnabled() const
+{
+ return (_videoEnabled);
+}
+
+void QZBar::setVideoEnabled(bool videoEnabled)
+{
+ if (!thread)
+ return;
+ if (_videoEnabled != videoEnabled) {
+ _videoEnabled = videoEnabled;
+ thread->pushEvent(new QZBarThread::VideoEnabledEvent(videoEnabled));
+ }
+}
+
+bool QZBar::isVideoOpened() const
+{
+ if (!thread)
+ return (false);
+ QMutexLocker locker(&thread->mutex);
+ return (thread->_videoOpened);
+}
+
+void QZBar::scanImage(const QImage &image)
+{
+ if (!thread)
+ return;
+ thread->pushEvent(new QZBarThread::ScanImageEvent(image));
+}
+
+void QZBar::dragEnterEvent(QDragEnterEvent *event)
+{
+ if (event->mimeData()->hasImage() || event->mimeData()->hasUrls())
+ event->acceptProposedAction();
+}
+
+void QZBar::dropEvent(QDropEvent *event)
+{
+ if (event->mimeData()->hasImage()) {
+ QImage image = qvariant_cast<QImage>(event->mimeData()->imageData());
+ scanImage(image);
+ event->setDropAction(Qt::CopyAction);
+ event->accept();
+ } else {
+ // FIXME TBD load URIs and queue for processing
+#if 0
+ std::cerr << "drop: "
+ << event->mimeData()->formats().join(", ").toStdString()
+ << std::endl;
+ QList<QUrl> urls = event->mimeData()->urls();
+ for(int i = 0; i < urls.size(); ++i)
+ std::cerr << "[" << i << "] "
+ << urls.at(i).toString().toStdString()
+ << std::endl;
+#endif
+ }
+}
+
+QSize QZBar::sizeHint() const
+{
+ if (!thread)
+ return (QSize(640, 480));
+ QMutexLocker locker(&thread->mutex);
+ return (QSize(thread->reqWidth, thread->reqHeight));
+}
+
+int QZBar::heightForWidth(int width) const
+{
+ if (thread) {
+ QMutexLocker locker(&thread->mutex);
+ int base_width = thread->reqWidth;
+ int base_height = thread->reqHeight;
+ if (base_width > 0 && base_height > 0)
+ return (base_height * width / base_width);
+ }
+ return (width * 3 / 4);
+}
+
+void QZBar::paintEvent(QPaintEvent *event)
+{
+ try {
+ if (thread)
+ thread->window.redraw();
+ } catch (Exception &) {
+ // sometimes Qt attempts to paint the widget before it's parented(?)
+ // just ignore this (can't throw from event anyway)
+ }
+}
+
+void QZBar::resizeEvent(QResizeEvent *event)
+{
+ QSize size = event->size();
+ try {
+ if (thread)
+ thread->window.resize(size.rwidth(), size.rheight());
+ } catch (Exception &) { /* ignore */
+ }
+}
+
+void QZBar::changeEvent(QEvent *event)
+{
+ try {
+ QMutexLocker locker(&thread->mutex);
+ if (event->type() == QEvent::ParentChange)
+#if QT_VERSION >= 0x050000
+ thread->window.attach(QX11Info::display(), winId());
+#else
+ thread->window.attach(x11Info().display(), winId());
+#endif
+
+ } catch (Exception &) { /* ignore (FIXME do something w/error) */
+ }
+}
+
+void QZBar::attach()
+{
+ if (_attached)
+ return;
+
+ try {
+#if QT_VERSION >= 0x050000
+ thread->window.attach(QX11Info::display(), winId());
+#else
+ thread->window.attach(x11Info().display(), winId());
+#endif
+ thread->window.resize(width(), height());
+ _attached = 1;
+
+ _videoEnabled = !_videoDevice.isEmpty();
+ if (_videoEnabled)
+ thread->pushEvent(new QZBarThread::VideoDeviceEvent(_videoDevice));
+ } catch (Exception &) { /* ignore (FIXME do something w/error) */
+ }
+}
+
+void QZBar::showEvent(QShowEvent *event)
+{
+ if (thread && !_attached)
+ attach();
+}
+
+void QZBar::sizeChange()
+{
+ update();
+ updateGeometry();
+}
diff --git a/qt/QZBarThread.cpp b/qt/QZBarThread.cpp
new file mode 100644
index 0000000..7675fa3
--- /dev/null
+++ b/qt/QZBarThread.cpp
@@ -0,0 +1,358 @@
+//------------------------------------------------------------------------
+// Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+//
+// This file is part of the ZBar Bar Code Reader.
+//
+// The ZBar Bar Code Reader is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser Public License as
+// published by the Free Software Foundation; either version 2.1 of
+// the License, or (at your option) any later version.
+//
+// The ZBar Bar Code Reader is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser Public License for more details.
+//
+// You should have received a copy of the GNU Lesser Public License
+// along with the ZBar Bar Code Reader; if not, write to the Free
+// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301 USA
+//
+// http://sourceforge.net/projects/zbar
+//------------------------------------------------------------------------
+
+#include "QZBarThread.h"
+#include <iostream>
+
+using namespace zbar;
+
+static const QString textFormat("%1:%2");
+
+QZBarThread::QZBarThread(int verbosity)
+ : _videoOpened(false), reqWidth(DEFAULT_WIDTH), reqHeight(DEFAULT_HEIGHT),
+ video(NULL), image(NULL), running(true), videoRunning(false),
+ videoEnabled(false)
+{
+ zbar_set_verbosity(verbosity);
+ scanner.set_handler(*this);
+}
+
+void QZBarThread::image_callback(Image &image)
+{
+ for (Image::SymbolIterator sym = image.symbol_begin();
+ sym != image.symbol_end(); ++sym)
+ if (!sym->get_count()) {
+ QString data = QString::fromStdString(sym->get_data());
+ emit decoded(sym->get_type(), data);
+
+ emit decodedText(textFormat.arg(
+ QString::fromStdString(sym->get_type_name()), data));
+ }
+}
+
+void QZBarThread::processImage(Image &image)
+{
+ {
+ scanner.recycle_image(image);
+ Image tmp = image.convert(*(long *)"Y800");
+ scanner.scan(tmp);
+ image.set_symbols(tmp.get_symbols());
+ }
+ window.draw(image);
+ if (this->image && this->image != &image) {
+ delete this->image;
+ this->image = NULL;
+ }
+ emit update();
+}
+
+void QZBarThread::enableVideo(bool enable)
+{
+ if (!video) {
+ videoRunning = videoEnabled = false;
+ return;
+ }
+ try {
+ scanner.enable_cache(enable);
+ video->enable(enable);
+ videoRunning = enable;
+ } catch (std::exception &e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ }
+ if (!enable) {
+ // release video image and revert to logo
+ clear();
+ emit update();
+ }
+}
+
+void QZBarThread::openVideo(const QString &device)
+{
+ if (videoRunning)
+ enableVideo(false);
+
+ {
+ QMutexLocker locker(&mutex);
+ videoEnabled = _videoOpened = false;
+ }
+
+ // ensure old video doesn't have image ref
+ // (FIXME handle video destroyed w/images outstanding)
+ clear();
+ emit update();
+
+ if (video) {
+ delete video;
+ video = NULL;
+ emit videoOpened(false);
+ }
+
+ if (device.isEmpty())
+ return;
+
+ try {
+ std::string devstr = device.toStdString();
+ video = new Video(devstr);
+
+ if (reqWidth != DEFAULT_WIDTH || reqHeight != DEFAULT_HEIGHT)
+ video->request_size(reqWidth, reqHeight);
+
+ negotiate_format(*video, window);
+ {
+ QMutexLocker locker(&mutex);
+ videoEnabled = _videoOpened = true;
+ reqWidth = video->get_width();
+ reqHeight = video->get_height();
+ }
+ currentDevice = device;
+
+ emit videoOpened(true);
+ } catch (std::exception &e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ emit videoOpened(false);
+ }
+}
+
+void QZBarThread::videoDeviceEvent(VideoDeviceEvent *e)
+{
+ openVideo(e->device);
+}
+
+void QZBarThread::videoEnabledEvent(VideoEnabledEvent *e)
+{
+ if (videoRunning && !e->enabled)
+ enableVideo(false);
+ videoEnabled = e->enabled;
+}
+
+void QZBarThread::scanImageEvent(ScanImageEvent *e)
+{
+ if (videoRunning)
+ enableVideo(false);
+
+ try {
+ image = new QZBarImage(e->image);
+ processImage(*image);
+ } catch (std::exception &e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ clear();
+ }
+}
+
+bool QZBarThread::event(QEvent *e)
+{
+ switch ((EventType)e->type()) {
+ case VideoDevice:
+ videoDeviceEvent((VideoDeviceEvent *)e);
+ break;
+ case VideoEnabled:
+ videoEnabledEvent((VideoEnabledEvent *)e);
+ break;
+ case ScanImage:
+ scanImageEvent((ScanImageEvent *)e);
+ break;
+ case Exit:
+ if (videoRunning)
+ enableVideo(false);
+ running = false;
+ break;
+ case ReOpen:
+ openVideo(currentDevice);
+ break;
+ default:
+ return (false);
+ }
+ return (true);
+}
+
+void QZBarThread::run()
+{
+ QEvent *e = NULL;
+ while (running) {
+ if (!videoEnabled) {
+ QMutexLocker locker(&mutex);
+ while (queue.isEmpty())
+ newEvent.wait(&mutex);
+ e = queue.takeFirst();
+ } else {
+ // release reference to any previous QImage
+ clear();
+ enableVideo(true);
+
+ while (videoRunning && !e) {
+ try {
+ Image image = video->next_image();
+ processImage(image);
+ } catch (std::exception &e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ enableVideo(false);
+ openVideo("");
+ }
+ QMutexLocker locker(&mutex);
+ if (!queue.isEmpty())
+ e = queue.takeFirst();
+ }
+
+ if (videoRunning)
+ enableVideo(false);
+ }
+ if (e) {
+ event(e);
+ delete e;
+ e = NULL;
+ }
+ }
+ clear();
+ openVideo("");
+}
+
+QVector<QPair<int, QString> > QZBarThread::get_menu(int index)
+{
+ QVector<QPair<int, QString> > vector;
+ struct video_controls_s *ctrl;
+
+ if (!video)
+ return vector;
+
+ ctrl = video->get_controls(index);
+ if (!ctrl)
+ return vector;
+
+ for (unsigned int i = 0; i < ctrl->menu_size; i++)
+ vector.append(qMakePair((int)ctrl->menu[i].value,
+ QString::fromUtf8(ctrl->menu[i].name)));
+
+ return vector;
+}
+
+int QZBarThread::get_controls(int index, char **name, char **group,
+ enum QZBar::ControlType *type, int *min, int *max,
+ int *def, int *step)
+{
+ struct video_controls_s *ctrl;
+
+ if (!video)
+ return 0;
+
+ ctrl = video->get_controls(index);
+ if (!ctrl)
+ return 0;
+
+ if (name)
+ *name = ctrl->name;
+ if (group)
+ *group = ctrl->group;
+ if (min)
+ *min = ctrl->min;
+ if (max)
+ *max = ctrl->max;
+ if (def)
+ *def = ctrl->def;
+ if (step)
+ *step = ctrl->step;
+
+ if (type) {
+ switch (ctrl->type) {
+ case VIDEO_CNTL_INTEGER:
+ *type = QZBar::Integer;
+ break;
+ case VIDEO_CNTL_MENU:
+ *type = QZBar::Menu;
+ break;
+ case VIDEO_CNTL_BUTTON:
+ *type = QZBar::Button;
+ break;
+ case VIDEO_CNTL_INTEGER64:
+ *type = QZBar::Integer64;
+ break;
+ case VIDEO_CNTL_STRING:
+ *type = QZBar::String;
+ break;
+ case VIDEO_CNTL_BOOLEAN:
+ *type = QZBar::Boolean;
+ break;
+ default:
+ *type = QZBar::Unknown;
+ break;
+ }
+ }
+
+ return 1;
+}
+
+int QZBarThread::set_control(char *name, bool value)
+{
+ if (!video)
+ return 0;
+
+ return video->set_control(name, value);
+}
+
+int QZBarThread::set_control(char *name, int value)
+{
+ if (!video)
+ return 0;
+
+ return video->set_control(name, value);
+}
+
+int QZBarThread::get_control(char *name, bool *value)
+{
+ if (!video)
+ return 0;
+
+ return video->get_control(name, value);
+}
+
+int QZBarThread::get_control(char *name, int *value)
+{
+ if (!video)
+ return 0;
+
+ return video->get_control(name, value);
+}
+
+void QZBarThread::request_size(unsigned width, unsigned height)
+{
+ reqWidth = width;
+ reqHeight = height;
+}
+
+int QZBarThread::get_resolution(int index, unsigned &width, unsigned &height,
+ float &max_fps)
+{
+ struct video_resolution_s *res;
+
+ if (!video)
+ return 0;
+
+ res = video->get_resolution(index);
+ if (!res)
+ return 0;
+
+ width = res->width;
+ height = res->height;
+ max_fps = res->max_fps;
+
+ return 1;
+}
diff --git a/qt/QZBarThread.h b/qt/QZBarThread.h
new file mode 100644
index 0000000..a54ecc8
--- /dev/null
+++ b/qt/QZBarThread.h
@@ -0,0 +1,192 @@
+//------------------------------------------------------------------------
+// Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+//
+// This file is part of the ZBar Bar Code Reader.
+//
+// The ZBar Bar Code Reader is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser Public License as
+// published by the Free Software Foundation; either version 2.1 of
+// the License, or (at your option) any later version.
+//
+// The ZBar Bar Code Reader is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser Public License for more details.
+//
+// You should have received a copy of the GNU Lesser Public License
+// along with the ZBar Bar Code Reader; if not, write to the Free
+// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301 USA
+//
+// http://sourceforge.net/projects/zbar
+//------------------------------------------------------------------------
+#ifndef _QZBARTHREAD_H_
+#define _QZBARTHREAD_H_
+
+#include <QEvent>
+#include <QMutex>
+#include <QThread>
+#include <QWaitCondition>
+#include <zbar.h>
+#include <zbar/QZBar.h>
+#include <zbar/QZBarImage.h>
+
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 480
+
+namespace zbar
+{
+class QZBarThread : public QThread, public Image::Handler
+{
+ Q_OBJECT
+
+public:
+ enum EventType
+ {
+ VideoDevice = QEvent::User,
+ VideoEnabled,
+ ScanImage,
+ ReOpen,
+ Exit = QEvent::MaxUser
+ };
+
+ class VideoDeviceEvent : public QEvent
+ {
+ public:
+ VideoDeviceEvent(const QString &device)
+ : QEvent((QEvent::Type)VideoDevice), device(device)
+ {
+ }
+ const QString device;
+ };
+
+ class VideoEnabledEvent : public QEvent
+ {
+ public:
+ VideoEnabledEvent(bool enabled)
+ : QEvent((QEvent::Type)VideoEnabled), enabled(enabled)
+ {
+ }
+ bool enabled;
+ };
+
+ class ScanImageEvent : public QEvent
+ {
+ public:
+ ScanImageEvent(const QImage &image)
+ : QEvent((QEvent::Type)ScanImage), image(image)
+ {
+ }
+ const QImage image;
+ };
+
+ QMutex mutex;
+ QWaitCondition newEvent;
+
+ // message queue for events passed from main gui thread to processor.
+ // (NB could(/should?) be QAbstractEventDispatcher except it doesn't
+ // work as documented!? ):
+ // protected by mutex
+ QList<QEvent *> queue;
+
+ // shared state:
+ // written by processor thread just after opening video or
+ // scanning an image, read by main gui thread during size_request.
+ // protected by mutex
+
+ bool _videoOpened;
+ unsigned reqWidth, reqHeight;
+
+ // window is also shared: owned by main gui thread.
+ // processor thread only calls draw(), clear() and negotiate_format().
+ // protected by its own internal lock
+
+ Window window;
+
+ QZBarThread(int verbosity = 0);
+
+ int get_controls(int index, char **name = NULL, char **group = NULL,
+ enum QZBar::ControlType *type = NULL, int *min = NULL,
+ int *max = NULL, int *def = NULL, int *step = NULL);
+ QVector<QPair<int, QString> > get_menu(int index);
+ int set_control(char *name, bool value);
+ int set_control(char *name, int value);
+ int get_control(char *name, bool *value);
+ int get_control(char *name, int *value);
+
+ int set_config(std::string cfgstr)
+ {
+ return scanner.set_config(cfgstr);
+ }
+
+ int set_config(zbar_symbol_type_t symbology, zbar_config_t config,
+ int value)
+ {
+ return scanner.set_config(symbology, config, value);
+ }
+
+ int get_config(zbar_symbol_type_t symbology, zbar_config_t config,
+ int &value)
+ {
+ return scanner.get_config(symbology, config, value);
+ }
+
+ void request_size(unsigned width, unsigned height);
+
+ int get_resolution(int index, unsigned &width, unsigned &height,
+ float &max_fps);
+
+ int request_dbus(bool enabled)
+ {
+ return scanner.request_dbus(enabled);
+ }
+
+ void pushEvent(QEvent *e)
+ {
+ QMutexLocker locker(&mutex);
+ queue.append(e);
+ newEvent.wakeOne();
+ }
+
+Q_SIGNALS:
+ void videoOpened(bool opened);
+ void update();
+ void decoded(int type, const QString &data);
+ void decodedText(const QString &data);
+
+protected:
+ void run();
+
+ void openVideo(const QString &device);
+ void enableVideo(bool enable);
+ void processImage(Image &image);
+
+ void clear()
+ {
+ window.clear();
+ if (image) {
+ delete image;
+ image = NULL;
+ }
+ }
+
+ virtual void image_callback(Image &image);
+
+ virtual bool event(QEvent *e);
+ virtual void videoDeviceEvent(VideoDeviceEvent *event);
+ virtual void videoEnabledEvent(VideoEnabledEvent *event);
+ virtual void scanImageEvent(ScanImageEvent *event);
+
+private:
+ Video *video;
+ ImageScanner scanner;
+ QZBarImage *image;
+ QString currentDevice;
+ bool running;
+ bool videoRunning;
+ bool videoEnabled;
+};
+
+}; // namespace zbar
+
+#endif