Reworking QtCamViewfinderRenderer to avoid having to pass QPainter to the renderer
[harmattan/cameraplus] / declarative / viewfinder.cpp
1 // -*- c++ -*-
2
3 /*!
4  * This file is part of CameraPlus.
5  *
6  * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #include "viewfinder.h"
24 #include "camera.h"
25 #include "cameraconfig.h"
26 #include "qtcamviewfinderrenderer.h"
27 #if defined(QT4)
28 #include <QDeclarativeInfo>
29 #elif defined(QT5)
30 #include <QQmlInfo>
31 #endif
32 #include <QPainter>
33 #include "qtcamdevice.h"
34
35 #if defined(QT4)
36 Viewfinder::Viewfinder(QDeclarativeItem *parent) :
37   QDeclarativeItem(parent),
38 #elif defined(QT5)
39 Viewfinder::Viewfinder(QQuickItem *parent) :
40   QQuickPaintedItem(parent),
41 #endif
42   m_renderer(0),
43   m_cam(0),
44   m_conf(0),
45   m_enabled(true) {
46
47 #if defined(QT4)
48   setFlag(QGraphicsItem::ItemHasNoContents, false);
49 #endif
50
51 #if defined(QT5)
52   setRenderTarget(QQuickPaintedItem::FramebufferObject);
53   setSmooth(false);
54   setAntialiasing(false);
55 #endif
56 }
57
58 Viewfinder::~Viewfinder() {
59
60 }
61
62 bool Viewfinder::isRenderingEnabled() const {
63   return m_enabled;
64 }
65
66 void Viewfinder::setRenderingEnabled(bool enabled) {
67   if (m_enabled != enabled) {
68     m_enabled = enabled;
69     emit renderingEnabledChanged();
70   }
71 }
72
73 Camera *Viewfinder::camera() const {
74   return m_cam;
75 }
76
77 void Viewfinder::setCamera(Camera *camera) {
78   if (m_cam == camera) {
79     return;
80   }
81
82   if (m_cam && m_cam != camera) {
83     qmlInfo(this) << "Cannot reset Camera";
84     return;
85   }
86
87   if (!camera) {
88     qmlInfo(this) << "Camera cannot be empty";
89     return;
90   }
91
92   if (m_cam) {
93     QObject::disconnect(m_cam, SIGNAL(deviceChanged()), this, SLOT(deviceChanged()));
94   }
95
96   m_cam = camera;
97
98   if (m_cam) {
99     QObject::connect(m_cam, SIGNAL(deviceChanged()), this, SLOT(deviceChanged()));
100   }
101
102   if (isComponentComplete()) {
103     deviceChanged();
104   }
105
106   emit cameraChanged();
107 }
108
109 CameraConfig *Viewfinder::cameraConfig() const {
110   return m_conf;
111 }
112
113 void Viewfinder::setCameraConfig(CameraConfig *config) {
114   if (m_conf && m_conf != config) {
115     qmlInfo(this) << "Cannot reset CameraConfig";
116     return;
117   }
118
119   if (!config) {
120     qmlInfo(this) << "CameraConfig cannot be empty";
121     return;
122   }
123
124   if (m_conf == config) {
125     return;
126   }
127
128   m_conf = config;
129
130   if (isComponentComplete()) {
131     deviceChanged();
132   }
133
134   emit cameraConfigChanged();
135 }
136
137 #if defined(QT4)
138 void Viewfinder::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
139                        QWidget *widget) {
140
141   Q_UNUSED(widget);
142   Q_UNUSED(option);
143   painter->fillRect(boundingRect(), Qt::black);
144 #elif defined(QT5)
145 void Viewfinder::paint(QPainter *painter) {
146   painter->fillRect(contentsBoundingRect(), Qt::black);
147 #endif
148
149   if (!m_renderer || !m_enabled) {
150     return;
151   }
152
153   bool needsNativePainting = m_renderer->needsNativePainting();
154
155   if (needsNativePainting) {
156     painter->beginNativePainting();
157   }
158
159   m_renderer->paint(QMatrix4x4(painter->combinedTransform()), painter->viewport());
160
161   if (needsNativePainting) {
162     painter->endNativePainting();
163   }
164 }
165
166 QRectF Viewfinder::renderArea() const {
167   return m_renderer ? m_renderer->renderArea() : QRectF();
168 }
169
170 QSizeF Viewfinder::videoResolution() const {
171   return m_renderer ? m_renderer->videoResolution() : QSizeF();
172 }
173
174 void Viewfinder::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) {
175 #if defined(QT4)
176   QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
177 #elif defined(QT5)
178   QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry);
179 #endif
180
181   if (m_renderer) {
182     m_renderer->resize(newGeometry.size());
183   }
184 }
185
186 void Viewfinder::componentComplete() {
187   if (!m_cam) {
188     qmlInfo(this) << "Camera not set";
189     return;
190   }
191
192   if (!m_conf) {
193     qmlInfo(this) << "CameraConfig not set";
194     return;
195   }
196
197   m_renderer = QtCamViewfinderRenderer::create(m_conf->config(), this);
198   if (!m_renderer) {
199     qmlInfo(this) << "Failed to create viewfinder renderer";
200     return;
201   }
202
203   m_renderer->resize(QSizeF(width(), height()));
204   QObject::connect(m_renderer, SIGNAL(updateRequested()), this, SLOT(updateRequested()));
205   QObject::connect(m_renderer, SIGNAL(renderAreaChanged()), this, SIGNAL(renderAreaChanged()));
206   QObject::connect(m_renderer, SIGNAL(videoResolutionChanged()), this, SIGNAL(videoResolutionChanged()));
207 }
208
209 void Viewfinder::deviceChanged() {
210   if (!m_renderer) {
211     qmlInfo(this) << "No renderer";
212     return;
213   }
214
215   QtCamDevice *dev = m_cam->device();
216
217   if (dev) {
218     dev->setViewfinder(this);
219   }
220
221   emit renderAreaChanged();
222   emit videoResolutionChanged();
223 }
224
225 GstElement *Viewfinder::sinkElement() {
226   return m_renderer ? m_renderer->sinkElement() : 0;
227 }
228
229 bool Viewfinder::setDevice(QtCamDevice *device) {
230   Q_UNUSED(device);
231
232   return true;
233 }
234
235 void Viewfinder::stop() {
236   if (m_renderer) {
237     m_renderer->reset();
238   }
239 }
240
241 void Viewfinder::updateRequested() {
242   if (m_enabled) {
243     update();
244   }
245 }