|
1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <QGesture> |
|
19 #include <QPainter> |
|
20 #include <hblabel.h> |
|
21 #include "hgcoverflowcontainer.h" |
|
22 #include "hgmediawallrenderer.h" |
|
23 #include "hgwidgetitem.h" |
|
24 #include "trace.h" |
|
25 |
|
26 |
|
27 static const qreal KCameraMaxYAngle(20); |
|
28 static const qreal KSpringVelocityToCameraYAngleFactor(2); |
|
29 static const int KLabelMargin(4); |
|
30 |
|
31 HgCoverflowContainer::HgCoverflowContainer( |
|
32 QGraphicsItem* parent) : HgContainer(parent), |
|
33 mTitleLabel(0), |
|
34 mDescriptionLabel(0), |
|
35 mTitlePosition(HgMediawall::PositionAboveImage), |
|
36 mDescriptionPosition(HgMediawall::PositionNone), |
|
37 mCenterIconTop(0), |
|
38 mPrevPos(-1) |
|
39 { |
|
40 mTitleLabel = new HbLabel(this); |
|
41 mTitleLabel->setZValue(zValue()+1); |
|
42 mTitleLabel->setAlignment(Qt::AlignCenter); |
|
43 mTitleLabel->setVisible(false); |
|
44 |
|
45 mDescriptionLabel = new HbLabel(this); |
|
46 mDescriptionLabel->setZValue(zValue()+1); |
|
47 mDescriptionLabel->setAlignment(Qt::AlignCenter); |
|
48 mDescriptionLabel->setVisible(false); |
|
49 } |
|
50 |
|
51 HgCoverflowContainer::~HgCoverflowContainer() |
|
52 { |
|
53 } |
|
54 |
|
55 // events |
|
56 void HgCoverflowContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) |
|
57 { |
|
58 HgContainer::paint(painter, option, widget); |
|
59 } |
|
60 |
|
61 void HgCoverflowContainer::resizeEvent(QGraphicsSceneResizeEvent *event) |
|
62 { |
|
63 FUNC_LOG; |
|
64 |
|
65 HbWidget::resizeEvent(event); |
|
66 |
|
67 QSizeF s(size()); |
|
68 qreal side = qMin(s.height()/1.8, s.width()/1.8); |
|
69 INFO("Setting image size to:" << side << "," << side); |
|
70 mRenderer->setImageSize(QSizeF(side, side)); |
|
71 mCenterIconTop = (s.height()-side)/2; |
|
72 |
|
73 positionLabels(); |
|
74 } |
|
75 |
|
76 // from HgContainer |
|
77 HgMediaWallRenderer* HgCoverflowContainer::createRenderer() |
|
78 { |
|
79 HgMediaWallRenderer* renderer = new HgMediaWallRenderer(this); |
|
80 renderer->setImageSize(QSizeF(200, 200)); |
|
81 renderer->enableCoverflowMode(true); |
|
82 renderer->setRowCount(1, renderer->getImageSize(), false); |
|
83 renderer->enableReflections(true); |
|
84 renderer->setSpacing(QSizeF(1,1)); |
|
85 renderer->setFrontCoverElevationFactor(0.5); |
|
86 return renderer; |
|
87 } |
|
88 |
|
89 qreal HgCoverflowContainer::getCameraDistance(qreal springVelocity) |
|
90 { |
|
91 return qAbs(springVelocity * 0.01f); |
|
92 } |
|
93 |
|
94 qreal HgCoverflowContainer::getCameraRotationY(qreal springVelocity) |
|
95 { |
|
96 return qBound(-KCameraMaxYAngle, springVelocity * KSpringVelocityToCameraYAngleFactor, KCameraMaxYAngle); |
|
97 } |
|
98 |
|
99 void HgCoverflowContainer::handleTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex) |
|
100 { |
|
101 Q_UNUSED(pos) |
|
102 |
|
103 if (qAbs(qreal(hitItemIndex) - mSpring.pos().x()) < 0.01f) |
|
104 { |
|
105 emit activated(hitItem->modelIndex()); |
|
106 } |
|
107 else |
|
108 { |
|
109 mSpring.animateToPos(QPointF(hitItemIndex, 0)); |
|
110 } |
|
111 } |
|
112 |
|
113 void HgCoverflowContainer::handleLongTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex) |
|
114 { |
|
115 Q_UNUSED(hitItemIndex) |
|
116 |
|
117 emit longPressed(hitItem->modelIndex(), pos); |
|
118 } |
|
119 |
|
120 void HgCoverflowContainer::onScrollPositionChanged(qreal pos) |
|
121 { |
|
122 HgContainer::onScrollPositionChanged(pos); |
|
123 |
|
124 if (mPrevPos != (int)pos) { |
|
125 mPrevPos = (int)pos; |
|
126 HgWidgetItem* item = itemByIndex((int)pos); |
|
127 if (item && item->modelIndex() != mSelectionModel->currentIndex()) { |
|
128 mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current); |
|
129 } |
|
130 } |
|
131 } |
|
132 |
|
133 void HgCoverflowContainer::handleCurrentChanged(const QModelIndex ¤t) |
|
134 { |
|
135 FUNC_LOG; |
|
136 |
|
137 if (current.isValid()) { |
|
138 updateLabels(current.row()); |
|
139 } |
|
140 } |
|
141 |
|
142 void HgCoverflowContainer::itemDataChanged(const int &firstIndex, const int &lastIndex) |
|
143 { |
|
144 FUNC_LOG; |
|
145 HANDLE_ERROR_NULL(mSelectionModel); // If model has been set, also is selection model |
|
146 |
|
147 HgContainer::itemDataChanged(firstIndex, lastIndex); |
|
148 |
|
149 if (mSelectionModel->currentIndex().isValid()) { |
|
150 int current = mSelectionModel->currentIndex().row(); |
|
151 if (firstIndex <= current && current <= lastIndex) { |
|
152 updateLabels(current); |
|
153 } |
|
154 } |
|
155 } |
|
156 |
|
157 void HgCoverflowContainer::setTitlePosition(HgMediawall::LabelPosition position) |
|
158 { |
|
159 FUNC_LOG; |
|
160 |
|
161 if (mTitlePosition != position) { |
|
162 mTitlePosition = position; |
|
163 positionLabels(); |
|
164 } |
|
165 } |
|
166 |
|
167 HgMediawall::LabelPosition HgCoverflowContainer::titlePosition() const |
|
168 { |
|
169 FUNC_LOG; |
|
170 |
|
171 return mTitlePosition; |
|
172 } |
|
173 |
|
174 void HgCoverflowContainer::setDescriptionPosition(HgMediawall::LabelPosition position) |
|
175 { |
|
176 FUNC_LOG; |
|
177 |
|
178 if (mDescriptionPosition != position) { |
|
179 mDescriptionPosition = position; |
|
180 positionLabels(); |
|
181 } |
|
182 } |
|
183 |
|
184 HgMediawall::LabelPosition HgCoverflowContainer::descriptionPosition() const |
|
185 { |
|
186 FUNC_LOG; |
|
187 |
|
188 return mDescriptionPosition; |
|
189 } |
|
190 |
|
191 void HgCoverflowContainer::setTitleFontSpec(const HbFontSpec &fontSpec) |
|
192 { |
|
193 FUNC_LOG; |
|
194 |
|
195 if (!mTitleLabel) return; |
|
196 if (mTitleLabel->fontSpec() != fontSpec) { |
|
197 mTitleLabel->setFontSpec(fontSpec); |
|
198 positionLabels(); |
|
199 } |
|
200 } |
|
201 |
|
202 HbFontSpec HgCoverflowContainer::titleFontSpec() const |
|
203 { |
|
204 FUNC_LOG; |
|
205 |
|
206 if (!mTitleLabel) return HbFontSpec(); |
|
207 return mTitleLabel->fontSpec(); |
|
208 } |
|
209 |
|
210 void HgCoverflowContainer::setDescriptionFontSpec(const HbFontSpec &fontSpec) |
|
211 { |
|
212 FUNC_LOG; |
|
213 |
|
214 if (!mDescriptionLabel) return; |
|
215 if (mDescriptionLabel->fontSpec() != fontSpec) { |
|
216 mDescriptionLabel->setFontSpec(fontSpec); |
|
217 positionLabels(); |
|
218 } |
|
219 } |
|
220 |
|
221 HbFontSpec HgCoverflowContainer::descriptionFontSpec() const |
|
222 { |
|
223 FUNC_LOG; |
|
224 |
|
225 if (!mDescriptionLabel) return HbFontSpec(); |
|
226 return mDescriptionLabel->fontSpec(); |
|
227 } |
|
228 |
|
229 void HgCoverflowContainer::positionLabels() |
|
230 { |
|
231 FUNC_LOG; |
|
232 HANDLE_ERROR_NULL(mTitleLabel); |
|
233 HANDLE_ERROR_NULL(mDescriptionLabel); |
|
234 HANDLE_ERROR_NULL(mSelectionModel); |
|
235 |
|
236 int height = size().height(); |
|
237 int width = size().width(); |
|
238 int titleHeight = QFontMetrics(mTitleLabel->effectiveFontSpec().font()).height(); |
|
239 int descriptionHeight = QFontMetrics(mDescriptionLabel->effectiveFontSpec().font()).height(); |
|
240 |
|
241 if (mTitlePosition == HgMediawall::PositionAboveImage && |
|
242 mDescriptionPosition == HgMediawall::PositionAboveImage) { |
|
243 mTitleLabel->setGeometry(QRectF( |
|
244 0, |
|
245 qMax(KLabelMargin, mCenterIconTop-2*KLabelMargin-titleHeight-descriptionHeight), |
|
246 width, titleHeight)); |
|
247 mDescriptionLabel->setGeometry(QRectF( |
|
248 0, |
|
249 mTitleLabel->geometry().bottom()+KLabelMargin, |
|
250 width, descriptionHeight)); |
|
251 } |
|
252 else if (mTitlePosition == HgMediawall::PositionBelowImage && |
|
253 mDescriptionPosition == HgMediawall::PositionBelowImage) { |
|
254 mDescriptionLabel->setGeometry(QRectF( |
|
255 0, |
|
256 height-descriptionHeight-KLabelMargin, |
|
257 width, descriptionHeight)); |
|
258 mTitleLabel->setGeometry(QRectF( |
|
259 0, |
|
260 mDescriptionLabel->geometry().top()-titleHeight-KLabelMargin, |
|
261 width, titleHeight)); |
|
262 } |
|
263 else { |
|
264 if (mTitlePosition == HgMediawall::PositionAboveImage) { |
|
265 mTitleLabel->setGeometry(QRectF( |
|
266 0, |
|
267 qMax(KLabelMargin, mCenterIconTop-KLabelMargin-titleHeight), |
|
268 width, titleHeight)); |
|
269 } |
|
270 else if (mTitlePosition == HgMediawall::PositionBelowImage) { |
|
271 mTitleLabel->setGeometry(QRectF( |
|
272 0, |
|
273 height-titleHeight-KLabelMargin, |
|
274 width, titleHeight)); |
|
275 } |
|
276 |
|
277 if (mDescriptionPosition == HgMediawall::PositionAboveImage) { |
|
278 mDescriptionLabel->setGeometry(QRectF( |
|
279 0, |
|
280 qMax(KLabelMargin, mCenterIconTop-KLabelMargin-descriptionHeight), |
|
281 width, descriptionHeight)); |
|
282 } |
|
283 else if (mDescriptionPosition == HgMediawall::PositionBelowImage) { |
|
284 mDescriptionLabel->setGeometry(QRectF( |
|
285 0, |
|
286 height-descriptionHeight-KLabelMargin, |
|
287 width, descriptionHeight)); |
|
288 } |
|
289 } |
|
290 |
|
291 mTitleLabel->setVisible(mTitlePosition != HgMediawall::PositionNone); |
|
292 mDescriptionLabel->setVisible(mDescriptionPosition != HgMediawall::PositionNone); |
|
293 |
|
294 INFO("Title geometry:" << mTitleLabel->geometry() << "visible:" << mTitleLabel->isVisible()); |
|
295 INFO("Description geometry:" << mDescriptionLabel->geometry() << "visible:" << mDescriptionLabel->isVisible()); |
|
296 |
|
297 if (mSelectionModel->currentIndex().isValid()) { |
|
298 updateLabels(mSelectionModel->currentIndex().row()); |
|
299 } |
|
300 } |
|
301 |
|
302 void HgCoverflowContainer::updateLabels(int itemIndex) |
|
303 { |
|
304 FUNC_LOG; |
|
305 HANDLE_ERROR_NULL(mTitleLabel); |
|
306 HANDLE_ERROR_NULL(mDescriptionLabel); |
|
307 |
|
308 if (itemIndex >= 0 && itemIndex < mItems.count()) { |
|
309 mTitleLabel->setPlainText(mItems.at(itemIndex)->title()); |
|
310 mDescriptionLabel->setPlainText(mItems.at(itemIndex)->description()); |
|
311 } |
|
312 } |
|
313 |
|
314 void HgCoverflowContainer::scrollToPosition(const QPointF& pos, bool animate) |
|
315 { |
|
316 QPointF p = pos; |
|
317 p.setX((int)pos.x()); |
|
318 HgContainer::scrollToPosition(p,animate); |
|
319 } |