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: FM Radio home screen widget |
|
15 * |
|
16 */ |
|
17 |
|
18 // System includes |
|
19 #include <HbPushButton> |
|
20 #include <HbLabel> |
|
21 #include <HbDocumentLoader> |
|
22 #include <HbFrameDrawer> |
|
23 #include <HbFrameItem> |
|
24 #include <HbIcon> |
|
25 #include <HbIconAnimationManager> |
|
26 #include <HbIconAnimationDefinition> |
|
27 #include <HbColorScheme> |
|
28 #include <QGraphicsLinearLayout> |
|
29 #include <QGraphicsItem> |
|
30 #include <QDesktopServices> |
|
31 #include <QTimer> |
|
32 |
|
33 // User includes |
|
34 #include "fmradiohswidget.h" |
|
35 #include "fmradiohswidgetprofilereader.h" |
|
36 #include "fmradiohswidgetradioserviceclient.h" |
|
37 #include "radioservicedef.h" |
|
38 #include "radio_global.h" |
|
39 #include "radiologger.h" |
|
40 |
|
41 /*! |
|
42 \ingroup group_fmradiohs_widget |
|
43 \class FmRadioHsWidget |
|
44 \brief Example implementation for home screen widget. |
|
45 |
|
46 FmRadioHsWidget implements needed functions for the FM Radio home screen |
|
47 widget. |
|
48 */ |
|
49 |
|
50 // ======== MEMBER FUNCTIONS ======== |
|
51 |
|
52 /*! |
|
53 Constructs a widget which is a child of \a parent, with widget flags set to \a flags. |
|
54 |
|
55 Constructor should be empty and all the actual construction should be |
|
56 done in onInitialize(). |
|
57 */ |
|
58 FmRadioHsWidget::FmRadioHsWidget(QGraphicsItem* parent, Qt::WindowFlags flags) |
|
59 : HbWidget(parent, flags), |
|
60 mTunerBackgroundPushButton(NULL), |
|
61 mPowerToggleButton(NULL), |
|
62 mPreviousPushButton(NULL), |
|
63 mNextPushButton(NULL), |
|
64 mInformationFirstRowLabel(NULL), |
|
65 mInformationSecondRowLabel(NULL), |
|
66 mFmRadioState(Undefined), |
|
67 mFavoriteStations(false), |
|
68 mRadioInformation(QHash<QString, QString>()), |
|
69 mProfileMonitor(NULL), |
|
70 mRadioServiceClient(NULL), |
|
71 mRadioStartingCancelTimer(NULL) |
|
72 { |
|
73 LOG_METHOD_ENTER; |
|
74 } |
|
75 |
|
76 /*! |
|
77 Destructor |
|
78 */ |
|
79 FmRadioHsWidget::~FmRadioHsWidget() |
|
80 { |
|
81 LOG_METHOD; |
|
82 } |
|
83 |
|
84 /*! |
|
85 Getter for /r mRootPath property. |
|
86 */ |
|
87 QString FmRadioHsWidget::rootPath()const |
|
88 { |
|
89 LOG_METHOD_ENTER; |
|
90 return mRootPath; |
|
91 } |
|
92 |
|
93 /*! |
|
94 Sets the mRoothPath propertry to /a roothPath. |
|
95 */ |
|
96 void FmRadioHsWidget::setRootPath(const QString &rootPath) |
|
97 { |
|
98 LOG_METHOD_ENTER; |
|
99 mRootPath = rootPath; |
|
100 } |
|
101 |
|
102 /*! |
|
103 Called when widget is initialized. Constructs objects and connects them. |
|
104 */ |
|
105 void FmRadioHsWidget::onInitialize() |
|
106 { |
|
107 LOG_METHOD_ENTER; |
|
108 mProfileMonitor = new FmRadioHsWidgetProfileReader(this); |
|
109 mRadioServiceClient = new FmRadioHsWidgetRadioServiceClient(this); |
|
110 mRadioStartingCancelTimer = new QTimer(this); |
|
111 |
|
112 connect(mRadioServiceClient, SIGNAL(radioInformationChanged(int, QVariant)), this, |
|
113 SLOT(handleRadioInformationChange(int, QVariant))); |
|
114 connect(mRadioServiceClient, SIGNAL(radioStateChanged(QVariant)), this, |
|
115 SLOT(handleRadioStateChange(QVariant))); |
|
116 connect(mProfileMonitor, SIGNAL(radioRunning(QVariant)), this, |
|
117 SLOT(handleRadioStateChange(QVariant))); |
|
118 |
|
119 load(KDocml); |
|
120 |
|
121 mProfileMonitor->startMonitoringRadioRunningStatus(); |
|
122 } |
|
123 |
|
124 /*! |
|
125 Called when widget is shown in the home screen |
|
126 */ |
|
127 void FmRadioHsWidget::onShow() |
|
128 { |
|
129 LOG_METHOD_ENTER; |
|
130 } |
|
131 |
|
132 /*! |
|
133 Called when widget is hidden from the home screen |
|
134 */ |
|
135 void FmRadioHsWidget::onHide() |
|
136 { |
|
137 LOG_METHOD_ENTER; |
|
138 } |
|
139 |
|
140 /*! |
|
141 Loads docml files. |
|
142 */ |
|
143 void FmRadioHsWidget::load(const QString &docml) |
|
144 { |
|
145 LOG_METHOD_ENTER; |
|
146 |
|
147 HbDocumentLoader *documentLoader = new HbDocumentLoader(); |
|
148 documentLoader->reset(); |
|
149 bool loaded = false; |
|
150 documentLoader->load(docml, &loaded); |
|
151 |
|
152 if (loaded) { |
|
153 // Find mainLayout |
|
154 HbWidget *mainLayout = qobject_cast<HbWidget*> (documentLoader->findWidget( |
|
155 KDocmlObjectNameMainLayout)); |
|
156 // For drawing frame backgrounds |
|
157 HbFrameItem *frameItem = NULL; |
|
158 |
|
159 if (mainLayout) { |
|
160 QGraphicsLinearLayout *mWidgetLayout = new QGraphicsLinearLayout(Qt::Vertical, this); |
|
161 |
|
162 // Temporarily use graphics from resources. Change to the system |
|
163 // graphics when they are available. |
|
164 HbFrameDrawer *drawer = new HbFrameDrawer( |
|
165 ":/ui/resource/qtg_graf_hsradio_bg.png", |
|
166 HbFrameDrawer::OnePiece); |
|
167 //HbFrameDrawer *drawer = new HbFrameDrawer("qtg_fr_hswidget_normal", |
|
168 // HbFrameDrawer::NinePieces); |
|
169 frameItem = new HbFrameItem(drawer, mainLayout); |
|
170 frameItem->setPreferredSize(mainLayout->preferredSize()); |
|
171 |
|
172 mWidgetLayout->addItem(mainLayout); |
|
173 setLayout(mWidgetLayout); |
|
174 } |
|
175 |
|
176 // Find stacked layout for tuner area. |
|
177 HbWidget *tunerStackedLayout = qobject_cast<HbWidget*> (documentLoader->findWidget( |
|
178 KDocmlObjectNameTunerStackedLayout)); |
|
179 if (tunerStackedLayout) { |
|
180 |
|
181 // Find stacked layout for information area. |
|
182 HbWidget *tunerInformationStackedLayout = qobject_cast<HbWidget*> (documentLoader->findWidget( |
|
183 KDocmlObjectNameTunerInformationStackedLayout)); |
|
184 if (tunerInformationStackedLayout) { |
|
185 |
|
186 // MarqueeItem tests. |
|
187 /* |
|
188 QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, mInformationAreaOneRowLayout); |
|
189 mInformationLonelyRowMarquee = new HbMarqueeItem(); |
|
190 mInformationLonelyRowMarquee->setObjectName("marquee3"); |
|
191 HbStyle::setItemName(mInformationLonelyRowMarquee, "marquee3"); |
|
192 mInformationLonelyRowMarquee->setText( |
|
193 "Long text"); |
|
194 mInformationLonelyRowMarquee->setLoopCount(-1); |
|
195 mInformationLonelyRowMarquee->startAnimation(); |
|
196 HbFontSpec fs(HbFontSpec::Secondary); |
|
197 mInformationLonelyRowMarquee->setFontSpec(fs); |
|
198 mInformationLonelyRowMarquee->setTextColor(HbColorScheme::color("qtc_hs_list_item_title")); |
|
199 mInformationLonelyRowMarquee->setPreferredSize(layout->preferredSize()); |
|
200 layout->addItem(mInformationLonelyRowMarquee); |
|
201 */ |
|
202 /* |
|
203 } |
|
204 */ |
|
205 |
|
206 // Find lonely label |
|
207 mInformationLonelyRowLabel = qobject_cast<HbLabel *> (documentLoader->findWidget( |
|
208 KDocmlObjectNameLonelyRowLabel)); |
|
209 if (mInformationLonelyRowLabel) { |
|
210 QColor color = HbColorScheme::color("qtc_radio_tuner_normal"); |
|
211 if (color.isValid()) { |
|
212 mInformationLonelyRowLabel->setTextColor(color); |
|
213 } |
|
214 } |
|
215 |
|
216 // Find layout for two rows |
|
217 mInformationAreaTwoRowsLayout = qobject_cast<QGraphicsWidget *> ( |
|
218 documentLoader->findObject(KDocmlObjectNameTwoRowsLayout)); |
|
219 if (mInformationAreaTwoRowsLayout) { |
|
220 // Find first row |
|
221 mInformationFirstRowLabel = qobject_cast<HbLabel *> (documentLoader->findWidget( |
|
222 KDocmlObjectNameFirstRowLabel)); |
|
223 if (mInformationFirstRowLabel) { |
|
224 QColor color = HbColorScheme::color("qtc_radio_tuner_normal"); |
|
225 if (color.isValid()) { |
|
226 mInformationFirstRowLabel->setTextColor(color); |
|
227 } |
|
228 } |
|
229 |
|
230 // Find second row |
|
231 mInformationSecondRowLabel = qobject_cast<HbLabel *> (documentLoader->findWidget( |
|
232 KDocmlObjectNameSecondRowLabel)); |
|
233 if (mInformationSecondRowLabel) { |
|
234 QColor color = HbColorScheme::color("qtc_radio_tuner_normal"); |
|
235 if (color.isValid()) { |
|
236 mInformationSecondRowLabel->setTextColor(color); |
|
237 } |
|
238 } |
|
239 |
|
240 } |
|
241 |
|
242 |
|
243 mAnimationIcon = qobject_cast<HbLabel *> (documentLoader->findWidget( |
|
244 KDocmlObjectNameAnimationIcon)); |
|
245 if (mAnimationIcon) { |
|
246 // Use animation manager to define the frame-by-frame animation. |
|
247 HbIconAnimationManager *animationManager = HbIconAnimationManager::global(); |
|
248 |
|
249 // Create animation definition. |
|
250 HbIconAnimationDefinition animationDefinition; |
|
251 QList<HbIconAnimationDefinition::AnimationFrame> animationFrameList; |
|
252 |
|
253 // This should be probably done by loading axml instead. |
|
254 HbIconAnimationDefinition::AnimationFrame animationFrame; |
|
255 QString animationFrameIconName; |
|
256 QString animationFrameIconNamePrefix = "qtg_anim_loading_"; |
|
257 for (int i = 1; i < 11; i++) { |
|
258 animationFrame.duration = 100; |
|
259 animationFrameIconName.clear(); |
|
260 animationFrameIconName.append(animationFrameIconNamePrefix); |
|
261 animationFrameIconName.append(animationFrameIconName.number(i)); |
|
262 animationFrame.iconName = animationFrameIconName; |
|
263 animationFrameList.append(animationFrame); |
|
264 } |
|
265 animationDefinition.setPlayMode(HbIconAnimationDefinition::Loop); |
|
266 animationDefinition.setFrameList(animationFrameList); |
|
267 animationManager->addDefinition("animation", animationDefinition); |
|
268 |
|
269 // Construct an icon using the animation definition. |
|
270 HbIcon icon("animation"); |
|
271 |
|
272 mAnimationIcon->setIcon(icon); |
|
273 } |
|
274 |
|
275 } |
|
276 |
|
277 // Find push button for tuner area. |
|
278 mTunerBackgroundPushButton = qobject_cast<HbPushButton*> (documentLoader->findWidget( |
|
279 KDocmlObjectNameTunerBackgroundPushButton)); |
|
280 if (mTunerBackgroundPushButton) { |
|
281 // Test different states. |
|
282 //bool p = mTunerBackgroundPushButton->setProperty("state", "normal"); |
|
283 // Try css for controlling the appearance. |
|
284 //bool b = QFile::exists(KCss); |
|
285 //bool cssLoaded = HbStyleLoader::registerFilePath(KCss); |
|
286 //HbStyle::setItemName(mTunerBackgroundPushButton, KDocmlObjectNameTunerBackgroundPushButton); |
|
287 // Use the frame background. |
|
288 HbFrameDrawer *tunerBackgroundButtonFrameDrawer = new HbFrameDrawer( |
|
289 "qtg_fr_tuner", HbFrameDrawer::ThreePiecesHorizontal); |
|
290 tunerBackgroundButtonFrameDrawer->setFillWholeRect(true); |
|
291 mTunerBackgroundPushButton->setFrameBackground(tunerBackgroundButtonFrameDrawer); |
|
292 |
|
293 // Connect the button's clicked signal. |
|
294 connect(mTunerBackgroundPushButton, SIGNAL(clicked()), this, SLOT(radioToForeground())); |
|
295 } |
|
296 |
|
297 } |
|
298 |
|
299 // Find layout for control buttons. |
|
300 HbWidget *controlButtonsLayout = qobject_cast<HbWidget*> (documentLoader->findWidget( |
|
301 KDocmlObjectNameContolButtonsLayout)); |
|
302 if (controlButtonsLayout) { |
|
303 if (frameItem) { |
|
304 // Stack widget's background behind it. |
|
305 frameItem->stackBefore(controlButtonsLayout); |
|
306 } |
|
307 |
|
308 // Find power button. |
|
309 mPowerToggleButton = qobject_cast<HbPushButton *> (documentLoader->findWidget( |
|
310 KDocmlObjectNameowerToggleButton)); |
|
311 if (mPowerToggleButton) { |
|
312 // If power button is lathced type, use this. |
|
313 //mPowerToggleButton->setCheckable(true); |
|
314 changeControlButtonFrameBackground(false, Left, mPowerToggleButton); |
|
315 |
|
316 // Use the graphics from resources until release contains proper graphics. |
|
317 mPowerToggleButton->setIcon(HbIcon(":/ui/resource/mono_power.png")); |
|
318 // Connect the button's clicked signal. |
|
319 connect(mPowerToggleButton, SIGNAL(clicked()), this, SLOT(radioToBackground())); |
|
320 } |
|
321 |
|
322 // Find previous button. |
|
323 mPreviousPushButton = qobject_cast<HbPushButton *> (documentLoader->findWidget( |
|
324 KDocmlObjectNamePreviousPushButton)); |
|
325 if (mPreviousPushButton) { |
|
326 changeControlButtonFrameBackground(false, Center, mPreviousPushButton); |
|
327 // Connect the button's clicked signal. |
|
328 connect(mPreviousPushButton, SIGNAL(clicked()), this, SLOT(previousChannel())); |
|
329 } |
|
330 |
|
331 // Find next button. |
|
332 mNextPushButton = qobject_cast<HbPushButton *> (documentLoader->findWidget( |
|
333 KDocmlObjectNameNextPushButton)); |
|
334 if (mNextPushButton) { |
|
335 changeControlButtonFrameBackground(false, Right, mNextPushButton); |
|
336 // Connect the button's clicked signal. |
|
337 connect(mNextPushButton, SIGNAL(clicked()), this, SLOT(nextChannel())); |
|
338 } |
|
339 } |
|
340 |
|
341 } |
|
342 // Loader is not needed anymore so it is deleted. |
|
343 delete documentLoader; |
|
344 } |
|
345 |
|
346 /*! |
|
347 Slot for closing FM Radio application from power button. |
|
348 */ |
|
349 void FmRadioHsWidget::closeRadio() |
|
350 { |
|
351 LOG_SLOT_CALLER; |
|
352 mRadioServiceClient->doCloseFmRadio(); |
|
353 } |
|
354 |
|
355 /*! |
|
356 Slot for previous button clicked. |
|
357 */ |
|
358 void FmRadioHsWidget::previousChannel() |
|
359 { |
|
360 LOG_SLOT_CALLER; |
|
361 clearRadioInformation(); |
|
362 mRadioServiceClient->doChangeFmRadioStation(FmRadioHsWidgetRadioServiceClient::PreviousFavouriteStation); |
|
363 } |
|
364 |
|
365 /*! |
|
366 Slot for next button clicked. |
|
367 */ |
|
368 void FmRadioHsWidget::nextChannel() |
|
369 { |
|
370 LOG_SLOT_CALLER; |
|
371 clearRadioInformation(); |
|
372 mRadioServiceClient->doChangeFmRadioStation(FmRadioHsWidgetRadioServiceClient::NextFavouriteStation); |
|
373 } |
|
374 |
|
375 /*! |
|
376 Slot for bringing the radio application to foreground. |
|
377 */ |
|
378 void FmRadioHsWidget::radioToForeground() |
|
379 { |
|
380 LOG_SLOT_CALLER; |
|
381 // If radio is not running start it to foreground by monitor request. |
|
382 if (mFmRadioState == NotRunning) { |
|
383 handleRadioStateChange(QVariant(Starting)); |
|
384 //mRadioServiceClient->doPowerOnFmRadio(FmRadioHsWidgetRadioServiceClient::ToForeground); |
|
385 mRadioServiceClient->startMonitoring(FmRadioHsWidgetRadioServiceClient::ToForeground); |
|
386 } |
|
387 else { |
|
388 if (mFmRadioState == Closing) { |
|
389 // Radio is closing but user wants to power it up again. |
|
390 mRadioServiceClient->doPowerOnFmRadio(); |
|
391 mRadioServiceClient->stopMonitoring(); |
|
392 mRadioServiceClient->startMonitoring(FmRadioHsWidgetRadioServiceClient::ToBackground); |
|
393 handleRadioStateChange(QVariant(Running)); |
|
394 } |
|
395 // If radio is running, bring it to the foreground. |
|
396 mRadioServiceClient->doChangeFmRadioVisibility( |
|
397 FmRadioHsWidgetRadioServiceClient::ToForeground); |
|
398 } |
|
399 } |
|
400 |
|
401 /*! |
|
402 Slot for putting the radio application to the background. |
|
403 */ |
|
404 void FmRadioHsWidget::radioToBackground() |
|
405 { |
|
406 LOG_SLOT_CALLER; |
|
407 // If radio is not running start it to background by monitor request. |
|
408 if (mFmRadioState == NotRunning) { |
|
409 handleRadioStateChange(QVariant(Starting)); |
|
410 mRadioServiceClient->startMonitoring(FmRadioHsWidgetRadioServiceClient::ToBackground); |
|
411 } |
|
412 else if (mFmRadioState == Starting) { |
|
413 // Do nothing if radio is starting. |
|
414 } |
|
415 else if (mFmRadioState == Closing) { |
|
416 // Radio is closing but user wants to power it up again. |
|
417 mRadioServiceClient->doPowerOnFmRadio(); |
|
418 mRadioServiceClient->stopMonitoring(); |
|
419 mRadioServiceClient->startMonitoring(FmRadioHsWidgetRadioServiceClient::ToBackground); |
|
420 handleRadioStateChange(QVariant(Running)); |
|
421 } |
|
422 else { |
|
423 // If radio is running, put it to the background. |
|
424 // This is little bit useless because the radio is in background if |
|
425 // user is able to click the widget. |
|
426 mRadioServiceClient->doChangeFmRadioVisibility( |
|
427 FmRadioHsWidgetRadioServiceClient::ToBackground); |
|
428 } |
|
429 } |
|
430 |
|
431 /*! |
|
432 Handles changes in FM Radio information. |
|
433 |
|
434 /param type Type of changed information. |
|
435 /param value Information content. |
|
436 */ |
|
437 void FmRadioHsWidget::handleRadioInformationChange(const int notificationId, |
|
438 const QVariant &value) |
|
439 { |
|
440 LOG_METHOD; |
|
441 LEVEL2(LOG_SLOT_CALLER); |
|
442 if (!value.isValid()) { |
|
443 // Value is not valid so return. |
|
444 return; |
|
445 } |
|
446 switch ( notificationId ) { |
|
447 |
|
448 case RadioServiceNotification::FavoriteCount: |
|
449 LEVEL2(LOG("FavoriteCount")); |
|
450 if (value.canConvert(QVariant::Int)) { |
|
451 int favoriteCount = value.toInt(); |
|
452 // If there are favorite stations, enable the next/previous |
|
453 // buttons. |
|
454 mFavoriteStations = favoriteCount > 0 ? true : false; |
|
455 LEVEL2(LOG_FORMAT("favoriteCount: %d, mFavoriteStations: %d", |
|
456 favoriteCount, mFavoriteStations)); |
|
457 changeStationButtonsEnabledState(mFavoriteStations); |
|
458 } |
|
459 break; |
|
460 |
|
461 case RadioServiceNotification::CurrentIsFavorite: |
|
462 LEVEL2(LOG("CurrentIsFavorite")); |
|
463 if (value.canConvert(QVariant::Bool)) { |
|
464 bool currentIsFavorite = value.toBool(); |
|
465 LEVEL2(LOG_FORMAT("currentIsFavorite: %d", currentIsFavorite)); |
|
466 // If favorite count is 1 and current station is favorite |
|
467 // disable next/prev buttons. |
|
468 if (currentIsFavorite) { |
|
469 changeStationButtonsEnabledState(false); |
|
470 } else { |
|
471 // Else eneble them. |
|
472 changeStationButtonsEnabledState(true); |
|
473 } |
|
474 } |
|
475 break; |
|
476 |
|
477 case RadioServiceNotification::RadioStatus: |
|
478 LEVEL2(LOG("RadioStatus")); |
|
479 if (value.canConvert(QVariant::Int)) { |
|
480 int status = value.toInt(); |
|
481 switch (status) { |
|
482 case RadioStatus::Playing: |
|
483 LEVEL2(LOG("Playing")); |
|
484 handleRadioStateChange(QVariant(ControllingAudio)); |
|
485 break; |
|
486 case RadioStatus::Muted: |
|
487 LEVEL2(LOG("Muted")); |
|
488 handleRadioStateChange(QVariant(NotControllingAudio)); |
|
489 break; |
|
490 case RadioStatus::Seeking: |
|
491 LEVEL2(LOG("Seeking")); |
|
492 handleRadioStateChange(QVariant(Seeking)); |
|
493 break; |
|
494 case RadioStatus::NoAntenna: |
|
495 LEVEL2(LOG("NoAntenna")); |
|
496 handleRadioStateChange(QVariant(AntennaNotConnected)); |
|
497 break; |
|
498 case RadioStatus::PoweringOff: |
|
499 LEVEL2(LOG("PoweringOff")); |
|
500 handleRadioStateChange(QVariant(Closing)); |
|
501 break; |
|
502 default: |
|
503 LEVEL2(LOG("default")); |
|
504 break; |
|
505 } |
|
506 } |
|
507 break; |
|
508 |
|
509 case RadioServiceNotification::Frequency: |
|
510 LEVEL2(LOG("Frequency")); |
|
511 if (value.canConvert(QVariant::UInt)) { |
|
512 const uint frequency = value.toUInt(); |
|
513 QString frequencyString; |
|
514 // Format the frequency to human readable text. |
|
515 frequencyString.sprintf("%.1f", qreal(frequency) / FREQUENCY_MULTIPLIER); |
|
516 LEVEL2(LOG_FORMAT("frequency: %s", GETSTRING(frequencyString))); |
|
517 // TODO: Remove comment when localisation is working on device. |
|
518 //frequencyString = hbTrId("txt_rad_list_l1_mhz").arg(freqString); |
|
519 bool frequencyCleared = false; |
|
520 // If widget has some frequency information and new frequency |
|
521 // differs from that |
|
522 if (mRadioInformation.contains(KRadioInformationFrequency) |
|
523 && mRadioInformation[KRadioInformationFrequency].compare(frequencyString) != 0) { |
|
524 // Clear all infromation from widget because station has changed. |
|
525 clearRadioInformation(); |
|
526 frequencyCleared = true; |
|
527 } |
|
528 // If widget do not have any frquency information, update it. |
|
529 bool frequencyUpdated = updateRadioInformation(KRadioInformationFrequency, frequencyString); |
|
530 if (frequencyCleared || frequencyUpdated) { |
|
531 // Information changed, update the UI. |
|
532 radioInformationChanged(); |
|
533 } |
|
534 } |
|
535 break; |
|
536 |
|
537 case RadioServiceNotification::Name: |
|
538 LEVEL2(LOG("Name")); |
|
539 if (value.canConvert(QVariant::String)) { |
|
540 if (updateRadioInformation(KRadioInformationStationName, value.toString())) { |
|
541 LEVEL2(LOG_FORMAT("name: %s", GETSTRING(value.toString()))); |
|
542 radioInformationChanged(); |
|
543 } |
|
544 } |
|
545 break; |
|
546 |
|
547 case RadioServiceNotification::Genre: |
|
548 LEVEL2(LOG("Genre")); |
|
549 if (value.canConvert(QVariant::String)) { |
|
550 if (updateRadioInformation(KRadioInformationPty, value.toString())) { |
|
551 LEVEL2(LOG_FORMAT("genre: %s", GETSTRING(value.toString()))); |
|
552 radioInformationChanged(); |
|
553 } |
|
554 } |
|
555 break; |
|
556 |
|
557 case RadioServiceNotification::RadioText: |
|
558 LEVEL2(LOG("RadioText")); |
|
559 if (value.canConvert(QVariant::String)) { |
|
560 if (updateRadioInformation(KRadioInformationRt, value.toString())) { |
|
561 LEVEL2(LOG_FORMAT("radio text: %s", GETSTRING(value.toString()))); |
|
562 radioInformationChanged(); |
|
563 } |
|
564 } |
|
565 break; |
|
566 |
|
567 case RadioServiceNotification::DynamicPS: |
|
568 LOG("DynamicPS"); |
|
569 if (value.canConvert(QVariant::String)) { |
|
570 if (updateRadioInformation(KRadioInformationDynamicPsName, value.toString())) { |
|
571 LEVEL2(LOG_FORMAT("dynamicPS: %s", GETSTRING(value.toString()))); |
|
572 radioInformationChanged(); |
|
573 } |
|
574 } |
|
575 break; |
|
576 |
|
577 default: |
|
578 LOG("default"); |
|
579 break; |
|
580 } |
|
581 } |
|
582 |
|
583 /*! |
|
584 Check if the the radio information is changed. If it is changed update it. |
|
585 |
|
586 /param informationType Type of the information. |
|
587 /param information Information text. |
|
588 |
|
589 /return bool If information is updated, return true. Return false otherwise. |
|
590 */ |
|
591 bool FmRadioHsWidget::updateRadioInformation(const QString &informationType, |
|
592 const QString &information) |
|
593 { |
|
594 LOG_METHOD_RET("%d"); |
|
595 // If hash contains this type of information. |
|
596 if (mRadioInformation.contains(informationType)) { |
|
597 // If new information is empty. |
|
598 if (information.isEmpty()) { |
|
599 // Remove old information from the hash. |
|
600 LEVEL2(LOG_FORMAT("informationType: %s removed", GETSTRING(informationType))); |
|
601 mRadioInformation.remove(informationType); |
|
602 // Return true to indicate the change. |
|
603 return true; |
|
604 } |
|
605 // If new information differs from the old one. |
|
606 if (mRadioInformation[informationType].compare(information) != 0) { |
|
607 // Update the information. |
|
608 LEVEL2(LOG_FORMAT("informationType: %s = %s", GETSTRING(informationType), GETSTRING(information))); |
|
609 mRadioInformation[informationType] = information; |
|
610 // And return true to indicate the change. |
|
611 return true; |
|
612 } |
|
613 } else { // Hash do not contain this type of information. |
|
614 // If new information is not empty. |
|
615 if (!information.isEmpty()) { |
|
616 // Add it to the hash. |
|
617 LEVEL2(LOG_FORMAT("informationType: %s = %s", GETSTRING(informationType), GETSTRING(information))); |
|
618 mRadioInformation[informationType] = information; |
|
619 // Return true to indicate the change. |
|
620 return true; |
|
621 } |
|
622 } |
|
623 // Return false to indicate that nothing changed. |
|
624 return false; |
|
625 } |
|
626 |
|
627 /*! |
|
628 Formatting radio information texts after a change. |
|
629 */ |
|
630 void FmRadioHsWidget::radioInformationChanged() |
|
631 { |
|
632 LOG_METHOD_ENTER; |
|
633 // Clear the rows. |
|
634 mRadioInformationFirstRow.clear(); |
|
635 mRadioInformationSecondRow.clear(); |
|
636 |
|
637 // First row contains station name. |
|
638 if (mRadioInformation.contains(KRadioInformationStationName)) { |
|
639 mRadioInformationFirstRow.append(mRadioInformation.value(KRadioInformationStationName)); |
|
640 } else if (mRadioInformation.contains(KRadioInformationFrequency)) { |
|
641 // Or frequency. |
|
642 mRadioInformationFirstRow.append(mRadioInformation.value(KRadioInformationFrequency)); |
|
643 } |
|
644 LEVEL2(LOG_FORMAT("mRadioInformationFirstRow: %s", GETSTRING(mRadioInformationFirstRow))); |
|
645 |
|
646 // Second row of information contains radio text. |
|
647 if (mRadioInformation.contains(KRadioInformationRt)) { |
|
648 mRadioInformationSecondRow.append(mRadioInformation.value(KRadioInformationRt)); |
|
649 } else if (mRadioInformation.contains(KRadioInformationDynamicPsName)) { |
|
650 // Or Dynamic PS name. |
|
651 mRadioInformationSecondRow.append(mRadioInformation.value( |
|
652 KRadioInformationDynamicPsName)); |
|
653 } else if (mRadioInformation.contains(KRadioInformationPty)) { |
|
654 // Or PTY. |
|
655 mRadioInformationSecondRow.append(mRadioInformation.value(KRadioInformationPty)); |
|
656 } |
|
657 LEVEL2(LOG_FORMAT("mRadioInformationSecondRow: %s", GETSTRING(mRadioInformationSecondRow))); |
|
658 |
|
659 // If second row is empty. |
|
660 if (mRadioInformationSecondRow.isEmpty()) { |
|
661 // Show only the lonely row. |
|
662 mInformationLonelyRowLabel->setPlainText(mRadioInformationFirstRow); |
|
663 changeInformationAreaLayout(OneRow); |
|
664 } |
|
665 else { |
|
666 // Else display both rows. |
|
667 mInformationFirstRowLabel->setPlainText(mRadioInformationFirstRow); |
|
668 mInformationSecondRowLabel->setPlainText(mRadioInformationSecondRow); |
|
669 changeInformationAreaLayout(TwoRows); |
|
670 } |
|
671 } |
|
672 |
|
673 /*! |
|
674 Clears the radio station information. For example, when the station is |
|
675 changed, old information should be cleared. |
|
676 */ |
|
677 void FmRadioHsWidget::clearRadioInformation() |
|
678 { |
|
679 LOG_METHOD_ENTER; |
|
680 if (!mRadioInformation.isEmpty()) { |
|
681 LEVEL2(LOG("clear radioInformation")); |
|
682 mRadioInformation.clear(); |
|
683 } |
|
684 } |
|
685 |
|
686 /*! |
|
687 Handles changes in FM Radio state. |
|
688 |
|
689 /param value New state of the radio application. |
|
690 */ |
|
691 void FmRadioHsWidget::handleRadioStateChange(const QVariant &value) |
|
692 { |
|
693 LOG_METHOD; |
|
694 int state; |
|
695 if (value.canConvert(QVariant::Int)) { |
|
696 state = value.toInt(); |
|
697 } else { |
|
698 return; |
|
699 } |
|
700 |
|
701 if (state == mFmRadioState) { |
|
702 // State did not change, so return. |
|
703 return; |
|
704 } |
|
705 |
|
706 switch (state) { |
|
707 case Undefined: |
|
708 LEVEL2(LOG("Undefined")); |
|
709 // Something went wrong. Widget should not be in this state after onInitialize(). |
|
710 mFmRadioState = Undefined; |
|
711 break; |
|
712 case NotRunning: |
|
713 LEVEL2(LOG("NotRunning")); |
|
714 mFmRadioState = NotRunning; |
|
715 mRadioServiceClient->stopMonitoring(); |
|
716 changePowerButtonOn(false); |
|
717 mFavoriteStations = false; |
|
718 changeStationButtonsEnabledState(false); |
|
719 clearRadioInformation(); |
|
720 mInformationFirstRowLabel->setPlainText(""); |
|
721 mInformationSecondRowLabel->setPlainText(""); |
|
722 mInformationLonelyRowLabel->setPlainText(hbTrId("txt_rad_list_fm_radio")); |
|
723 changeInformationAreaLayout(OneRow); |
|
724 break; |
|
725 case Starting: |
|
726 LEVEL2(LOG("Starting")); |
|
727 mFmRadioState = Starting; |
|
728 changePowerButtonOn(true); |
|
729 changeStationButtonsEnabledState(false); |
|
730 changeInformationAreaLayout(Animation); |
|
731 // This timer is workaround to recover from situation where radio is |
|
732 // started from widget but user answers no to the offline start dialog. |
|
733 // Stop timer if it is running. |
|
734 stopRadioStartingCancelTimer(); |
|
735 // Set timer as single shot. |
|
736 mRadioStartingCancelTimer->setSingleShot(true); |
|
737 // Connect timeout. |
|
738 connect(mRadioStartingCancelTimer, SIGNAL(timeout()), this, |
|
739 SLOT(cancelRadioStartingState())); |
|
740 // Start to timeout after delay. |
|
741 mRadioStartingCancelTimer->start(KRadioStartingStateCancelDelay); |
|
742 break; |
|
743 case Running: |
|
744 LEVEL2(LOG("Running")); |
|
745 mFmRadioState = Running; |
|
746 // Stop timer if it is running because radio is now running. |
|
747 stopRadioStartingCancelTimer(); |
|
748 mRadioServiceClient->startMonitoring( |
|
749 FmRadioHsWidgetRadioServiceClient::DoNotChange); |
|
750 changePowerButtonOn(true); |
|
751 changeStationButtonsEnabledState(mFavoriteStations); |
|
752 changeInformationAreaLayout(OneRow); |
|
753 break; |
|
754 case ControllingAudio: |
|
755 LEVEL2(LOG("ControllingAudio")); |
|
756 mFmRadioState = ControllingAudio; |
|
757 changeStationButtonsEnabledState(mFavoriteStations); |
|
758 radioInformationChanged(); |
|
759 break; |
|
760 case NotControllingAudio: |
|
761 LEVEL2(LOG("NotControllingAudio")); |
|
762 mFmRadioState = NotControllingAudio; |
|
763 changeStationButtonsEnabledState(mFavoriteStations); |
|
764 radioInformationChanged(); |
|
765 break; |
|
766 case Seeking: |
|
767 LEVEL2(LOG("Seeking")); |
|
768 mFmRadioState = Seeking; |
|
769 changeStationButtonsEnabledState(false); |
|
770 changeInformationAreaLayout(Animation); |
|
771 break; |
|
772 case AntennaNotConnected: |
|
773 LEVEL2(LOG("AntennaNotConnected")); |
|
774 mFmRadioState = AntennaNotConnected; |
|
775 changeStationButtonsEnabledState(false); |
|
776 mInformationFirstRowLabel->setPlainText(""); |
|
777 mInformationSecondRowLabel->setPlainText(""); |
|
778 mInformationLonelyRowLabel->setPlainText(hbTrId("txt_rad_info_connect_wired_headset")); |
|
779 changeInformationAreaLayout(OneRow); |
|
780 break; |
|
781 case Closing: |
|
782 LEVEL2(LOG("Closing")); |
|
783 mFmRadioState = Closing; |
|
784 changePowerButtonOn(false); |
|
785 changeStationButtonsEnabledState(false); |
|
786 clearRadioInformation(); |
|
787 mInformationFirstRowLabel->setPlainText(""); |
|
788 mInformationSecondRowLabel->setPlainText(""); |
|
789 mInformationLonelyRowLabel->setPlainText(hbTrId("txt_rad_list_fm_radio")); |
|
790 changeInformationAreaLayout(OneRow); |
|
791 break; |
|
792 default: |
|
793 LOG("default"); |
|
794 break; |
|
795 } |
|
796 } |
|
797 |
|
798 /*! |
|
799 Changes visible widgets of information area stacked layout. |
|
800 |
|
801 /param InformationAreaLayout The layout to switch visible. |
|
802 */ |
|
803 void FmRadioHsWidget::changeInformationAreaLayout(const InformationAreaLayout layout) |
|
804 { |
|
805 LOG_METHOD; |
|
806 switch (layout) { |
|
807 case OneRow: |
|
808 LEVEL2(LOG("OneRow")); |
|
809 mInformationLonelyRowLabel->show(); |
|
810 mInformationAreaTwoRowsLayout->hide(); |
|
811 mAnimationIcon->hide(); |
|
812 break; |
|
813 case TwoRows: |
|
814 LEVEL2(LOG("TwoRows")); |
|
815 mInformationLonelyRowLabel->hide(); |
|
816 mInformationAreaTwoRowsLayout->show(); |
|
817 mAnimationIcon->hide(); |
|
818 break; |
|
819 case Animation: |
|
820 LEVEL2(LOG("Animation")); |
|
821 mInformationLonelyRowLabel->hide(); |
|
822 mInformationAreaTwoRowsLayout->hide(); |
|
823 mAnimationIcon->show(); |
|
824 break; |
|
825 default: |
|
826 LOG("default"); |
|
827 break; |
|
828 } |
|
829 } |
|
830 |
|
831 /*! |
|
832 Changes state of power button. |
|
833 |
|
834 */ |
|
835 void FmRadioHsWidget::changePowerButtonOn(const bool isPowerOn) |
|
836 { |
|
837 LOG_METHOD; |
|
838 QString iconName; |
|
839 if (isPowerOn) { |
|
840 LEVEL2(LOG("Power on")); |
|
841 // Change icon to reflect power on state. |
|
842 iconName.append("qtg_mono_power"); |
|
843 mPowerToggleButton->setIcon(HbIcon(":/ui/resource/mono_power.png")); |
|
844 mPowerToggleButton->setText("Off"); |
|
845 // Connect clicked to closeRadio slot. |
|
846 disconnect(mPowerToggleButton, SIGNAL(clicked()), this, |
|
847 SLOT(radioToBackground())); |
|
848 connect(mPowerToggleButton, SIGNAL(clicked()), this, |
|
849 SLOT(closeRadio())); |
|
850 } else { |
|
851 LEVEL2(LOG("Power off")); |
|
852 // Change icon to reflect power off state. |
|
853 iconName.append("qtg_mono_power"); |
|
854 mPowerToggleButton->setIcon(HbIcon(":/ui/resource/mono_power.png")); |
|
855 mPowerToggleButton->setText("On"); |
|
856 // Connect clicked to radioToBackground slot. |
|
857 disconnect(mPowerToggleButton, SIGNAL(clicked()), this, |
|
858 SLOT(closeRadio())); |
|
859 connect(mPowerToggleButton, SIGNAL(clicked()), this, |
|
860 SLOT(radioToBackground())); |
|
861 } |
|
862 changeControlButtonFrameBackground(true, Left, mPowerToggleButton); |
|
863 } |
|
864 |
|
865 /*! |
|
866 Changes enabled state of station buttons. |
|
867 |
|
868 */ |
|
869 void FmRadioHsWidget::changeStationButtonsEnabledState(const bool enabled) |
|
870 { |
|
871 LOG_METHOD_ENTER; |
|
872 changeControlButtonFrameBackground(enabled, Center, mPreviousPushButton); |
|
873 changeControlButtonFrameBackground(enabled, Right, mNextPushButton); |
|
874 } |
|
875 |
|
876 /*! |
|
877 Changes background of control button. |
|
878 |
|
879 /param enabled Is button enabled or disabled. |
|
880 /param position Position of the control button in button group. |
|
881 /param button The button to change the background. |
|
882 */ |
|
883 void FmRadioHsWidget::changeControlButtonFrameBackground(const bool enabled, |
|
884 const ControlButtonPosition position, HbPushButton *button) |
|
885 { |
|
886 LOG_METHOD_ENTER; |
|
887 QString frameGraphicsName("qtg_fr_hsbutton_"); |
|
888 if (enabled) { |
|
889 frameGraphicsName.append("normal"); |
|
890 } else { |
|
891 frameGraphicsName.append("disabled"); |
|
892 } |
|
893 LEVEL2(LOG_FORMAT("frameGraphicsName: %s", GETSTRING(frameGraphicsName))); |
|
894 HbFrameDrawer *frameDrawer = new HbFrameDrawer(frameGraphicsName, |
|
895 HbFrameDrawer::ThreePiecesHorizontal); |
|
896 switch (position) { |
|
897 case Left: |
|
898 LEVEL2(LOG("Left")); |
|
899 frameDrawer->setFileNameSuffixList(QStringList() << "_l" << "_c" << "_cr"); |
|
900 break; |
|
901 case Center: |
|
902 LEVEL2(LOG("Center")); |
|
903 frameDrawer->setFileNameSuffixList(QStringList() << "_cl" << "_c" << "_cr"); |
|
904 break; |
|
905 case Right: |
|
906 LEVEL2(LOG("Right")); |
|
907 frameDrawer->setFileNameSuffixList(QStringList() << "_cl" << "_c" << "_r"); |
|
908 break; |
|
909 default: |
|
910 LOG("default"); |
|
911 break; |
|
912 } |
|
913 button->setFrameBackground(frameDrawer); |
|
914 button->setEnabled(enabled); |
|
915 } |
|
916 |
|
917 /*! |
|
918 Radio did not start on time. Let's reset the widget's state. |
|
919 |
|
920 */ |
|
921 void FmRadioHsWidget::cancelRadioStartingState() |
|
922 { |
|
923 LOG_SLOT_CALLER; |
|
924 handleRadioStateChange(QVariant(NotRunning)); |
|
925 } |
|
926 |
|
927 /*! |
|
928 Stop the timer canceling radio starting state. |
|
929 |
|
930 */ |
|
931 void FmRadioHsWidget::stopRadioStartingCancelTimer() |
|
932 { |
|
933 LOG_METHOD_ENTER; |
|
934 if (mRadioStartingCancelTimer->isActive()) { |
|
935 mRadioStartingCancelTimer->stop(); |
|
936 } |
|
937 } |
|