zxing/symbian/QQrDecoder/QCameraControllerWidget.cpp
ftylitak@gmail.com e1aab01022 Updated Symbian project QQrDecoder. It now supports the latest devices and Symbian OSs (Symbian^3, Belle, Anna).
Uses Qt SDK + Camera APIs from Qt Mobility.

Updated the tutorial which shows how to use it.

Updated the installation file included to test without compiling (also advice the tutorial for details).

git-svn-id: https://zxing.googlecode.com/svn/trunk@1920 59b500cc-1b3d-0410-9834-0bbf25fbcc57
2011-09-19 10:32:17 +00:00

355 lines
11 KiB
C++

/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/
#include "QCameraControllerWidget.h"
//#include <QDebug>
/*****************************************************************************
* QCameraControllerWidget
*/
QCameraControllerWidget::QCameraControllerWidget(QWidget *parent) :
QWidget(parent)
{
setWindowTitle("QCameraControllerWidget");
// Opitimizations for screen update and drawing qwidget
setAutoFillBackground(false);
// Prevent to screensaver to activate
// m_systemScreenSaver = new QSystemScreenSaver(this);
// m_systemScreenSaver->setScreenSaverInhibit();
m_myVideoSurface = 0;
pictureCaptured = false;
showViewFinder = false;
m_focusing = false;
// Black background
QPalette palette = this->palette();
palette.setColor(QPalette::Background, Qt::black);
setPalette(palette);
// Main widget & layout
// QWidget* mainWidget = new QWidget(this);
setPalette(palette);
QHBoxLayout* hboxl = new QHBoxLayout;
hboxl->setSpacing(0);
hboxl->setMargin(0);
// UI stack
m_stackedWidget = new QStackedWidget();
m_stackedWidget->setPalette(palette);
// First widget to stack
m_videoWidget = new QWidget();
m_videoWidget->setPalette(palette);
m_stackedWidget->addWidget(m_videoWidget);
// Second widget to stack
QWidget* secondWidget = new QWidget(this);
secondWidget->setPalette(palette);
m_stackedWidget->addWidget(secondWidget);
m_stackedWidget->setCurrentIndex(0);
hboxl->addWidget(m_stackedWidget);
// Buttons
QSize iconSize(80, 80);
QVBoxLayout* vboxl = new QVBoxLayout;
vboxl->setSpacing(0);
vboxl->setMargin(0);
// Exit button
m_exit = new Button(this);
QObject::connect(m_exit, SIGNAL(pressed()), qApp, SLOT(quit()));
QPixmap p = QPixmap(":/icons/exit.png");
m_exit->setPixmap(p.scaled(iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
vboxl->addWidget(m_exit);
vboxl->setAlignment(m_exit,Qt::AlignHCenter | Qt::AlignTop);
// Camera button
m_cameraBtn = new Button(this);
QObject::connect(m_cameraBtn, SIGNAL(pressed()), this, SLOT(searchAndLock()));
p = QPixmap(":/icons/camera.png");
m_cameraBtn->setPixmap(p.scaled(iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
vboxl->addWidget(m_cameraBtn);
vboxl->setAlignment(m_cameraBtn, Qt::AlignBottom);
hboxl->addLayout(vboxl);
setLayout(hboxl);
// Enable camera after 1s, so that the application is started
// and widget is created to landscape orientation
QTimer::singleShot(1000,this,SLOT(enableCamera()));
}
QCameraControllerWidget::~QCameraControllerWidget()
{
if (m_myVideoSurface)
m_myVideoSurface->stop();
m_camera->stop();
delete m_stackedWidget;
delete m_stillImageCapture;
delete m_camera;
}
void QCameraControllerWidget::enableCamera()
{
m_camera = new QCamera();
m_camera->setCaptureMode(QCamera::CaptureStillImage);
connect(m_camera, SIGNAL(error(QCamera::Error)), this, SLOT(error(QCamera::Error)));
connect(m_camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)), this, SLOT(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)));
// Own video output drawing that shows camera view finder pictures
//! [0]
QMediaService* ms = m_camera->service();
QVideoRendererControl* vrc = ms->requestControl<QVideoRendererControl*>();
m_myVideoSurface = new MyVideoSurface(this,this,this);
vrc->setSurface(m_myVideoSurface);
//! [0]
// Image capturer
m_stillImageCapture = new QCameraImageCapture(m_camera);
connect(m_stillImageCapture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(onImageCaptured(int,QImage)));
// Start camera
if (m_camera->state() == QCamera::ActiveState) {
m_camera->stop();
}
m_videoWidget->show();
m_camera->start();
showViewFinder = true;
}
void QCameraControllerWidget::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
if (pictureCaptured) {
// Starting view finder
pictureCaptured = false;
m_stackedWidget->setCurrentIndex(0);
if (m_myVideoSurface) {
showViewFinder = true;
}
}
}
void QCameraControllerWidget::searchAndLock()
{
m_focusing = false;
m_focusMessage.clear();
if (pictureCaptured) {
// Starting view finder again
pictureCaptured = false;
m_stackedWidget->setCurrentIndex(0);
if (m_myVideoSurface) {
showViewFinder = true;
}
}
else {
// Search and lock picture (=focus)
if (m_camera->supportedLocks() & QCamera::LockFocus) {
m_focusing = true;
m_focusMessage = "Focusing...";
m_camera->searchAndLock(QCamera::LockFocus);
} else {
// No focus functionality, take picture right away
captureImage();
}
}
}
void QCameraControllerWidget::lockStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason)
{
if (status == QCamera::Locked) {
if (reason == QCamera::LockAcquired) {
// Focus locked
m_focusMessage.clear();
m_focusing = false;
// Capture new image
captureImage();
// Unlock camera
m_camera->unlock();
} else {
if (m_focusing)
m_focusMessage = "No focus, try again";
}
} else if (status == QCamera::Unlocked && m_focusing) {
m_focusMessage = "No focus, try again";
}
}
void QCameraControllerWidget::captureImage()
{
if (pictureCaptured) {
// Starting view finder again
pictureCaptured = false;
m_stackedWidget->setCurrentIndex(0);
showViewFinder = true;
}
else {
// Capturing image
showViewFinder = false;
// Get picture location where to store captured images
QString path(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation));
QDir dir(path);
// Get next filename
QStringList files = dir.entryList(QStringList() << "camera_*.jpg");
int lastImage = 0;
foreach ( QString fileName, files ) {
int imgNumber = fileName.mid(7, fileName.size() - 11).toInt();
lastImage = qMax(lastImage, imgNumber);
}
// Capture image
if (m_stillImageCapture->isReadyForCapture()) {
m_imageName = QString("camera_%1.jpg").arg(lastImage+1);
m_stillImageCapture->capture(m_imageName);
}
}
}
void QCameraControllerWidget::onImageCaptured(int id, const QImage &preview)
{
m_stillImageCapture->cancelCapture();
showViewFinder = false;
m_focusing = false;
// Image captured, show it to the user
m_stackedWidget->setCurrentIndex(1);
// Get picture location
QString path(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation));
m_imageName.prepend(path + "/");
m_capturedImage = preview;
// Set suitable size to the image
QSize s = m_videoWidget->size();
s = s - QSize(20, 20);
m_capturedImage = m_capturedImage.scaled(s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
emit imageCaptured(preview);
pictureCaptured = true;
update();
}
void QCameraControllerWidget::error(QCamera::Error e)
{
switch (e) {
case QCamera::NoError:
{
break;
}
case QCamera::CameraError:
{
QMessageBox::warning(this, "QCameraControllerWidget", "General Camera error");
break;
}
case QCamera::InvalidRequestError:
{
QMessageBox::warning(this, "QCameraControllerWidget", "Camera invalid request error");
break;
}
case QCamera::ServiceMissingError:
{
QMessageBox::warning(this, "QCameraControllerWidget", "Camera service missing error");
break;
}
case QCamera::NotSupportedFeatureError :
{
QMessageBox::warning(this, "QCameraControllerWidget", "Camera not supported error");
break;
}
};
}
void QCameraControllerWidget::updateVideo()
{
if (showViewFinder) {
repaint();
}
}
void QCameraControllerWidget::paintEvent(QPaintEvent *event)
{
//QMainWindow::paintEvent(event);
QPainter painter(this);
QRect r = this->rect();
QFont font = painter.font();
font.setPixelSize(20);
painter.setFont(font);
painter.setPen(Qt::white);
if (showViewFinder && m_myVideoSurface && m_myVideoSurface->isActive()) {
// Show view finder
m_myVideoSurface->paint(&painter);
// Paint focus message
if (!m_focusMessage.isEmpty())
painter.drawText(r, Qt::AlignCenter, m_focusMessage);
} else {
// Draw black
painter.fillRect(event->rect(), palette().background());
// Show captured image
if (pictureCaptured) {
// Paint captured image
QPoint centerPic((qAbs(r.size().width() - m_capturedImage.size().width())) / 2, (qAbs(
r.size().height() - m_capturedImage.size().height())) / 2);
painter.drawImage(centerPic, m_capturedImage);
// Paint filename
// painter.drawText(r, Qt::AlignBottom | Qt::AlignCenter, m_imageName);
}
}
}