|
1 /* |
|
2 * Copyright (c) 2009 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 <QGraphicsSceneMouseEvent> |
|
19 #include <QGraphicsLinearLayout> |
|
20 #include <QDir> |
|
21 |
|
22 #include <HbMainWindow> |
|
23 #include <HbInputMethod> |
|
24 |
|
25 #include "hsidlewidget.h" |
|
26 #include "hsscene.h" |
|
27 #include "hspage.h" |
|
28 #include "hswidgethost.h" |
|
29 #include "hswallpaper.h" |
|
30 #include "hstrashbinwidget.h" |
|
31 #include "hspageindicator.h" |
|
32 #include "hsdocumentloader.h" |
|
33 |
|
34 namespace |
|
35 { |
|
36 const char CONTROL_LAYER_DOCML_FILE[] = "controllayer.docml"; |
|
37 const char CONTROL_LAYER[] = "controlLayer"; |
|
38 const char TRASH_BIN[] = "trashBin"; |
|
39 const char PAGE_INDICATOR[] = "pageIndicator"; |
|
40 } |
|
41 |
|
42 /*! |
|
43 \class HsIdleWidget |
|
44 \ingroup group_hshomescreenstateplugin |
|
45 \brief View part of the home screen idle state. |
|
46 |
|
47 Maintains the idle view ui layers and takes care of |
|
48 receiving user input and communicating it to the idle |
|
49 state for further processing. |
|
50 */ |
|
51 |
|
52 /*! |
|
53 Constructs a new idle widget with the given \a parent. |
|
54 */ |
|
55 HsIdleWidget::HsIdleWidget(QGraphicsItem *parent) |
|
56 : HbWidget(parent), |
|
57 mControlLayer(0), mPageLayer(0), mSceneLayer(0), |
|
58 mDelayedPressEvent(0), |
|
59 mTrashBin(0), mPageIndicator(0) |
|
60 { |
|
61 setFlag(ItemHasNoContents); |
|
62 |
|
63 loadControlLayer(); |
|
64 |
|
65 QGraphicsLinearLayout *linearLayout = 0; |
|
66 |
|
67 linearLayout = new QGraphicsLinearLayout(Qt::Horizontal); |
|
68 linearLayout->setContentsMargins(0, 0, 0, 0); |
|
69 linearLayout->setSpacing(0); |
|
70 mPageLayer = new HbWidget(this); |
|
71 mPageLayer->setLayout(linearLayout); |
|
72 mPageLayer->setZValue(1); |
|
73 |
|
74 linearLayout = new QGraphicsLinearLayout(Qt::Horizontal); |
|
75 linearLayout->setContentsMargins(0, 0, 0, 0); |
|
76 linearLayout->setSpacing(0); |
|
77 mSceneLayer = new HbWidget(this); |
|
78 mSceneLayer->setLayout(linearLayout); |
|
79 mSceneLayer->setZValue(0); |
|
80 } |
|
81 |
|
82 /*! |
|
83 Destroys this idle widget. |
|
84 */ |
|
85 HsIdleWidget::~HsIdleWidget() |
|
86 { |
|
87 clearDelayedPress(); |
|
88 |
|
89 QList<HsPage *> pages = HsScene::instance()->pages(); |
|
90 foreach (HsPage *page, pages) { |
|
91 page->setParentItem(0); |
|
92 if (page->scene()) { |
|
93 page->scene()->removeItem(page); |
|
94 } |
|
95 } |
|
96 |
|
97 HsWallpaper *wallpaper = HsScene::instance()->wallpaper(); |
|
98 wallpaper->setParentItem(0); |
|
99 if (wallpaper->scene()) { |
|
100 wallpaper->scene()->removeItem(wallpaper); |
|
101 } |
|
102 } |
|
103 |
|
104 /*! |
|
105 Layouts the ui layers according to the given \a rect. |
|
106 */ |
|
107 void HsIdleWidget::setGeometry(const QRectF &rect) |
|
108 { |
|
109 int n = HsScene::instance()->pages().count(); |
|
110 mControlLayer->resize(rect.size()); |
|
111 mPageLayer->resize(n * rect.width(), rect.height()); |
|
112 mSceneLayer->resize(2 * rect.width(), rect.height()); |
|
113 HbWidget::setGeometry(rect); |
|
114 } |
|
115 |
|
116 /*! |
|
117 Stores the given mouse press \a event. |
|
118 */ |
|
119 void HsIdleWidget::captureDelayedPress(QGraphicsSceneMouseEvent *event) |
|
120 { |
|
121 if (event) { |
|
122 mDelayedPressEvent = new QMouseEvent(QEvent::MouseButtonPress, |
|
123 event->scenePos().toPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
|
124 mDelayedPressEvent->setAccepted(false); |
|
125 } |
|
126 } |
|
127 |
|
128 /*! |
|
129 Sends the stored mouse press event. |
|
130 */ |
|
131 void HsIdleWidget::sendDelayedPress() |
|
132 { |
|
133 if (mDelayedPressEvent) { |
|
134 QApplication::sendEvent(HsScene::mainWindow()->viewport(), mDelayedPressEvent); |
|
135 clearDelayedPress(); |
|
136 } |
|
137 } |
|
138 |
|
139 /*! |
|
140 Deletes the stored mouse press event. |
|
141 */ |
|
142 void HsIdleWidget::clearDelayedPress() |
|
143 { |
|
144 if (mDelayedPressEvent) { |
|
145 delete mDelayedPressEvent; |
|
146 mDelayedPressEvent = 0; |
|
147 } |
|
148 } |
|
149 |
|
150 /*! |
|
151 Sets the active page \a index to the page |
|
152 indicator. |
|
153 */ |
|
154 void HsIdleWidget::setActivePage(int index) |
|
155 { |
|
156 mPageIndicator->setCurrentIndex(index); |
|
157 } |
|
158 |
|
159 /*! |
|
160 Inserts the given \a page at index position |
|
161 \a index in the page layer. |
|
162 */ |
|
163 void HsIdleWidget::insertPage(int index, HsPage *page) |
|
164 { |
|
165 QGraphicsLinearLayout *layout = |
|
166 static_cast<QGraphicsLinearLayout *>(mPageLayer->layout()); |
|
167 layout->insertItem(index, page); |
|
168 mPageLayer->resize( |
|
169 layout->count() * size().width(), size().height()); |
|
170 } |
|
171 |
|
172 /*! |
|
173 Removes the page at index position |
|
174 \a index in the page layer. |
|
175 */ |
|
176 void HsIdleWidget::removePage(int index) |
|
177 { |
|
178 QGraphicsLinearLayout *layout = |
|
179 static_cast<QGraphicsLinearLayout *>(mPageLayer->layout()); |
|
180 layout->removeAt(index); |
|
181 mPageLayer->resize( |
|
182 layout->count() * size().width(), size().height()); |
|
183 } |
|
184 |
|
185 /*! |
|
186 \fn HsIdleWidget::controlLayer() const |
|
187 |
|
188 Returns the control layer. |
|
189 */ |
|
190 |
|
191 /*! |
|
192 \fn HsIdleWidget::pageLayer() const |
|
193 |
|
194 Returns the page layer. |
|
195 */ |
|
196 |
|
197 /*! |
|
198 \fn HsIdleWidget::sceneLayer() const |
|
199 |
|
200 Returns the scene layer. |
|
201 */ |
|
202 |
|
203 /*! |
|
204 \fn HsIdleWidget::trashBin() const |
|
205 |
|
206 Returns the trashbin widget. |
|
207 */ |
|
208 |
|
209 /*! |
|
210 \fn HsIdleWidget::pageIndicator() const |
|
211 |
|
212 Returns the page indicator widget. |
|
213 */ |
|
214 |
|
215 /*! |
|
216 \fn HsIdleWidget::mousePressed(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &) |
|
217 |
|
218 The idle state connects to this signal for handling mouse |
|
219 press events. It filters events for the item \a watched. |
|
220 \a event is the filtered event. Sets the \a filtered true |
|
221 if the event was filtered by this handler. |
|
222 */ |
|
223 |
|
224 /*! |
|
225 \fn HsIdleWidget::mouseMoved(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &) |
|
226 |
|
227 The idle state connects to this signal for handling mouse |
|
228 move events. It filters events for the item \a watched. |
|
229 \a event is the filtered event. Sets the \a filtered true |
|
230 if the event was filtered by this handler. |
|
231 */ |
|
232 |
|
233 /*! |
|
234 \fn HsIdleWidget::mouseReleased(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &) |
|
235 |
|
236 The idle state connects to this signal for handling mouse |
|
237 release events. It filters events for the item \a watched. |
|
238 \a event is the filtered event. Sets the \a filtered true |
|
239 if the event was filtered by this handler. |
|
240 */ |
|
241 |
|
242 /*! |
|
243 Sets the trashbin visible and hides the page indicator. |
|
244 */ |
|
245 void HsIdleWidget::showTrashBin() |
|
246 { |
|
247 mPageIndicator->hide(); |
|
248 mTrashBin->show(); |
|
249 } |
|
250 |
|
251 /*! |
|
252 Sets the page indicator visible and hides the trashbin. |
|
253 */ |
|
254 void HsIdleWidget::showPageIndicator() |
|
255 { |
|
256 mTrashBin->hide(); |
|
257 mTrashBin->deactivate(); |
|
258 mPageIndicator->setVisible(1 < mPageIndicator->itemCount()); |
|
259 } |
|
260 |
|
261 /*! |
|
262 Filters the main window's graphics scene (\a object) \a event. |
|
263 */ |
|
264 bool HsIdleWidget::eventFilter(QObject *object, QEvent *event) |
|
265 { |
|
266 Q_UNUSED(object) |
|
267 |
|
268 if (HbInputMethod::activeInputMethod() && |
|
269 HbInputMethod::activeInputMethod()->focusObject()) { |
|
270 setFiltersChildEvents(false); |
|
271 return false; |
|
272 } |
|
273 |
|
274 bool filtered = false; |
|
275 |
|
276 switch (event->type()) { |
|
277 case QEvent::GraphicsSceneMousePress: |
|
278 if (mDelayedPressEvent && |
|
279 scene()->mouseGrabberItem()) { |
|
280 scene()->mouseGrabberItem()->ungrabMouse(); |
|
281 } |
|
282 setFiltersChildEvents(!mDelayedPressEvent); |
|
283 break; |
|
284 case QEvent::GraphicsSceneMouseMove: |
|
285 emit mouseMoved(0, static_cast<QGraphicsSceneMouseEvent *>(event), filtered); |
|
286 break; |
|
287 case QEvent::GraphicsSceneMouseRelease: |
|
288 setItemsFocusable(); |
|
289 emit mouseReleased(0, static_cast<QGraphicsSceneMouseEvent *>(event), filtered); |
|
290 if (filtered && scene()->mouseGrabberItem()) { |
|
291 scene()->mouseGrabberItem()->ungrabMouse(); |
|
292 } |
|
293 break; |
|
294 default: |
|
295 break; |
|
296 } |
|
297 |
|
298 return filtered; |
|
299 } |
|
300 |
|
301 /*! |
|
302 Filters events for the item \a watched. \a event is the filtered event. |
|
303 */ |
|
304 bool HsIdleWidget::sceneEventFilter(QGraphicsItem *watched, QEvent *event) |
|
305 { |
|
306 bool filtered = false; |
|
307 |
|
308 switch (event->type()) { |
|
309 case QEvent::GraphicsSceneMousePress: |
|
310 emit mousePressed(watched, static_cast<QGraphicsSceneMouseEvent *>(event), filtered); |
|
311 if (filtered) { |
|
312 setItemsUnfocusable(static_cast<QGraphicsSceneMouseEvent *>(event)); |
|
313 } |
|
314 break; |
|
315 default: |
|
316 break; |
|
317 } |
|
318 |
|
319 return filtered; |
|
320 } |
|
321 |
|
322 /*! |
|
323 Reimplements QGraphicsWidget::polishEvent(). |
|
324 */ |
|
325 void HsIdleWidget::polishEvent() |
|
326 { |
|
327 HsScene *scene = HsScene::instance(); |
|
328 Q_ASSERT(scene); |
|
329 |
|
330 QGraphicsLinearLayout *layout = |
|
331 static_cast<QGraphicsLinearLayout *>(mPageLayer->layout()); |
|
332 QList<HsPage *> pages = scene->pages(); |
|
333 foreach (HsPage *page, pages) { |
|
334 layout->addItem(page); |
|
335 } |
|
336 |
|
337 layout = static_cast<QGraphicsLinearLayout *>(mSceneLayer->layout()); |
|
338 HsWallpaper *wallpaper = HsScene::instance()->wallpaper(); |
|
339 layout->addItem(wallpaper); |
|
340 |
|
341 mPageIndicator->setItemCount(pages.count()); |
|
342 setActivePage(scene->activePageIndex()); |
|
343 showPageIndicator(); |
|
344 |
|
345 HsScene::mainWindow()->scene()->installEventFilter(this); |
|
346 } |
|
347 |
|
348 /*! |
|
349 Loads the control layer declared in a docml file. |
|
350 */ |
|
351 void HsIdleWidget::loadControlLayer() |
|
352 { |
|
353 HsDocumentLoader loader; |
|
354 bool loaded = false; |
|
355 |
|
356 #ifndef Q_OS_SYMBIAN |
|
357 QString path = QDir::currentPath(); |
|
358 #else |
|
359 QString path = "c:"; |
|
360 #endif |
|
361 |
|
362 QString file = path + "/hsresources/" + CONTROL_LAYER_DOCML_FILE; |
|
363 QString fallbackPath = QString(":/") + CONTROL_LAYER_DOCML_FILE; |
|
364 |
|
365 if (QFile::exists(file)) { |
|
366 loader.load(file, &loaded); |
|
367 if (!loaded) { |
|
368 loader.load(fallbackPath, &loaded); |
|
369 } |
|
370 } else { |
|
371 loader.load(fallbackPath, &loaded); |
|
372 } |
|
373 |
|
374 if (loaded) { |
|
375 mControlLayer = qobject_cast<HbWidget *>(loader.findWidget(CONTROL_LAYER)); |
|
376 mControlLayer->setZValue(2); |
|
377 mControlLayer->setParentItem(this); |
|
378 |
|
379 mTrashBin = qobject_cast<HsTrashBinWidget *>(loader.findWidget(TRASH_BIN)); |
|
380 mTrashBin->setZValue(1e6); |
|
381 |
|
382 mPageIndicator = qobject_cast<HsPageIndicator *>(loader.findWidget(PAGE_INDICATOR)); |
|
383 mPageIndicator->setZValue(1e6); |
|
384 } else { |
|
385 // TODO: Handle error. |
|
386 } |
|
387 } |
|
388 |
|
389 /*! |
|
390 Sets the items under the given mouse \a event scene position |
|
391 unfocusable and stores the items. |
|
392 */ |
|
393 void HsIdleWidget::setItemsUnfocusable(QGraphicsSceneMouseEvent *event) |
|
394 { |
|
395 mFocusableItems.clear(); |
|
396 QList<QGraphicsItem *> items = |
|
397 HsScene::mainWindow()->scene()->items(event->scenePos()); |
|
398 int i = 0; |
|
399 while (!mPageLayer->isAncestorOf(items[i++])) {} |
|
400 HsPage *page = HsScene::instance()->activePage(); |
|
401 QList<HsWidgetHost *> widgets = page->widgets(); |
|
402 for (; i < items.count(); ++i) { |
|
403 QGraphicsItem *item = items.at(i); |
|
404 if (page->isAncestorOf(item)) { |
|
405 foreach (HsWidgetHost *widget, widgets) { |
|
406 if ((item == widget || widget->isAncestorOf(item))&& item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { |
|
407 if (!item->isWidget() || static_cast<QGraphicsWidget*>(item)->focusPolicy() & Qt::ClickFocus) { |
|
408 item->setFlag(QGraphicsItem::ItemIsFocusable, false); |
|
409 mFocusableItems.append(item); |
|
410 } |
|
411 } |
|
412 } |
|
413 } |
|
414 } |
|
415 } |
|
416 |
|
417 /*! |
|
418 Sets the stored items focusable. |
|
419 */ |
|
420 void HsIdleWidget::setItemsFocusable() |
|
421 { |
|
422 foreach (QGraphicsItem *item, mFocusableItems) { |
|
423 item->setFlag(QGraphicsItem::ItemIsFocusable); |
|
424 } |
|
425 mFocusableItems.clear(); |
|
426 } |