14 * Description: |
14 * Description: |
15 * |
15 * |
16 */ |
16 */ |
17 |
17 |
18 // System includes |
18 // System includes |
19 #include <QPainter> |
|
20 #include <QStringListModel> |
|
21 #include <QGraphicsSceneResizeEvent> |
|
22 #include <QPen> |
|
23 #include <HbPushButton> |
|
24 #include <QTimer> |
|
25 #include <HbColorScheme> |
|
26 #include <HbEvent> |
|
27 #include <HbSwipeGesture> |
|
28 #include <HbDeviceProfile> |
|
29 |
19 |
|
20 // User includes |
30 #include "radiofrequencystrip.h" |
21 #include "radiofrequencystrip.h" |
31 #include "radiofrequencyitem.h" |
|
32 #include "radiouiengine.h" |
22 #include "radiouiengine.h" |
33 #include "radiostation.h" |
23 #include "radiostation.h" |
34 #include "radiostationmodel.h" |
24 #include "radiostationmodel.h" |
35 #include "radioutil.h" |
25 #include "radioutil.h" |
36 #include "radiouiloader.h" |
26 #include "radiouiloader.h" |
37 #include "radiologger.h" |
27 #include "radiologger.h" |
38 |
28 |
39 // Frequency lines |
|
40 const int TAB_HEIGHT_SMALL = 12; |
|
41 const int TAB_HEIGHT_BIG = 18; |
|
42 const int PEN_WIDTH_FAVORITE = 4; |
|
43 const qreal INDICATOR_WIDTH = 2.0; |
|
44 |
|
45 const qreal ROUNDER = 0.5; |
|
46 const int SELECTOR_WIDTH = 2; |
|
47 const int SELECTOR_Z_POS = 100; |
|
48 |
|
49 const int HALF_HERTZ = ONE_HERTZ / 2; |
|
50 const int ONE_TAB_DISTANCE = 20; |
|
51 const uint ONE_TAB_IN_HZ = uint( 0.2 * ONE_HERTZ ); |
|
52 const qreal PIXEL_IN_HZ = ONE_TAB_IN_HZ / ONE_TAB_DISTANCE; |
|
53 const qreal PIXMAP_OVERLAP = qreal( ONE_TAB_DISTANCE ) / 2; |
|
54 const int ITEM_WIDTH = ONE_TAB_DISTANCE * 5; |
|
55 const int PIXMAP_WIDTH = ITEM_WIDTH + (int)PIXMAP_OVERLAP; |
|
56 |
|
57 const uint ONE_HUNDRED_KHZ = 100000; |
|
58 |
|
59 const char* DECIMAL_TEXT = ".0"; |
|
60 |
|
61 #ifdef BUILD_WIN32 |
|
62 const int FREQUENCY_FONT_SIZE = 12; |
|
63 const int DECIMAL_FONT_SIZE = 8; |
|
64 #else |
|
65 const int FREQUENCY_FONT_SIZE = 6; |
|
66 const int DECIMAL_FONT_SIZE = 4; |
|
67 #endif // BUILD_WIN32 |
|
68 |
|
69 const QFont FREQUENCY_FONT( "", FREQUENCY_FONT_SIZE ); |
|
70 const QFont DECIMAL_FONT( "", DECIMAL_FONT_SIZE ); |
|
71 |
|
72 const char* SLIDE_TO_LEFT = "SlideToLeft"; |
|
73 const char* SLIDE_FROM_LEFT = "SlideFromLeft"; |
|
74 const char* SLIDE_TO_RIGHT = "SlideToRight"; |
|
75 const char* SLIDE_FROM_RIGHT = "SlideFromRight"; |
|
76 const char* LEFT_BUTTON = "tv:left_button"; |
|
77 const char* RIGHT_BUTTON = "tv:right_button"; |
|
78 |
|
79 const char* TEXT_COLOR_ATTRIBUTE = "text"; |
|
80 const int MANUALSEEK_START_TIMEOUT = 400; |
|
81 const int MANUALSEEK_END_TIMEOUT = 2000; |
|
82 const int MANUALSEEK_SIGNAL_DELAY = 300; |
|
83 |
|
84 /*! |
|
85 * |
|
86 */ |
|
87 RadioFrequencyStrip::RadioFrequencyStrip() : |
29 RadioFrequencyStrip::RadioFrequencyStrip() : |
88 RadioStripBase(), |
30 RadioFrequencyStripBase(), |
89 mUiEngine( NULL ), |
31 mUiEngine( NULL ) |
90 mItemHeight( 8 ), |
|
91 mMinFrequency( 87500000 ), |
|
92 mMaxFrequency( 108000000 ), |
|
93 mFrequencyStepSize( 100000 ), |
|
94 mFrequency( 87500000 ), |
|
95 mSelectorImage( new QGraphicsPixmapItem( this ) ), |
|
96 mSeparatorPos( 0.0 ), |
|
97 mMaxWidth( 0 ), |
|
98 mSelectorPos( 0.0 ), |
|
99 mLeftButton( 0 ), |
|
100 mRightButton( 0 ), |
|
101 mManualSeekTimer( NULL ), |
|
102 mManualSeekMode( false ), |
|
103 mLastReportedFrequency( 0 ), |
|
104 mManualSeekTimerId( 0 ), |
|
105 mForegroundColor( Qt::white )//HbColorScheme::color( TEXT_COLOR_ATTRIBUTE ) ) |
|
106 { |
32 { |
107 RadioUtil::setFrequencyStrip( this ); |
33 RadioUtil::setFrequencyStrip( this ); |
108 |
|
109 setScrollingStyle( HbScrollArea::PanWithFollowOn ); |
|
110 setItemSize( QSizeF( ITEM_WIDTH + PIXMAP_OVERLAP / 2, mItemHeight ) ); |
|
111 setOverlap( PIXMAP_OVERLAP / 2 ); |
|
112 } |
|
113 |
|
114 /*! |
|
115 * Property |
|
116 */ |
|
117 void RadioFrequencyStrip::setItemHeight( int itemHeight ) |
|
118 { |
|
119 mItemHeight = itemHeight; |
|
120 } |
|
121 |
|
122 /*! |
|
123 * Property |
|
124 */ |
|
125 int RadioFrequencyStrip::itemHeight() const |
|
126 { |
|
127 return mItemHeight; |
|
128 } |
34 } |
129 |
35 |
130 /*! |
36 /*! |
131 * |
37 * |
132 */ |
38 */ |
133 void RadioFrequencyStrip::init( RadioUiEngine* engine, RadioUiLoader& uiLoader ) |
39 void RadioFrequencyStrip::init( RadioUiEngine* engine, RadioUiLoader& uiLoader ) |
134 { |
40 { |
135 mUiEngine = engine; |
41 mUiEngine = engine; |
136 mMinFrequency = mUiEngine->minFrequency(); |
42 initbase( mUiEngine->minFrequency(), mUiEngine->maxFrequency(), |
137 mMaxFrequency = mUiEngine->maxFrequency(); |
43 mUiEngine->frequencyStepSize(), RadioUiEngine::lastTunedFrequency() ); |
138 mFrequencyStepSize = mUiEngine->frequencyStepSize(); |
|
139 mFrequency = RadioUiEngine::lastTunedFrequency(); |
|
140 |
44 |
141 initModel(); |
45 createButtonsFromDocml( uiLoader, DOCML::MV_NAME_PREV_BUTTON, DOCML::MV_NAME_NEXT_BUTTON ); |
142 initEmptyItems(); |
|
143 initPositions(); |
|
144 |
|
145 HbDeviceProfile deviceProfile; |
|
146 mItemHeight = static_cast<int>( mItemHeight * deviceProfile.unitValue() ); |
|
147 |
|
148 mLeftButton = uiLoader.findWidget<HbPushButton>( DOCML::MV_NAME_PREV_BUTTON ); |
|
149 mRightButton = uiLoader.findWidget<HbPushButton>( DOCML::MV_NAME_NEXT_BUTTON ); |
|
150 initButtons(); |
|
151 |
|
152 mManualSeekTimer = new QTimer( this ); |
|
153 mManualSeekTimer->setInterval( MANUALSEEK_START_TIMEOUT ); |
|
154 mManualSeekTimer->setSingleShot( true ); |
|
155 Radio::connect( mManualSeekTimer, SIGNAL(timeout()), |
|
156 this, SLOT(toggleManualSeek()) ); |
|
157 |
|
158 Radio::connect( mLeftButton, SIGNAL(clicked()), |
|
159 this, SLOT(handleLeftButton()) ); |
|
160 Radio::connect( mRightButton, SIGNAL(clicked()), |
|
161 this, SLOT(handleRightButton()) ); |
|
162 Radio::connect( mLeftButton, SIGNAL(longPress(QPointF)), |
|
163 this, SLOT(handleLongLeftButton()) ); |
|
164 Radio::connect( mRightButton, SIGNAL(longPress(QPointF)), |
|
165 this, SLOT(handleLongRightButton()) ); |
|
166 |
|
167 Radio::connect( this, SIGNAL(scrollingEnded()), |
|
168 this, SLOT(handleScrollingEnd()) ); |
|
169 |
|
170 grabGesture( Qt::SwipeGesture ); |
|
171 |
|
172 //TODO: Remove. Stepsize hardcoded to 100 Khz in europe region during demo |
|
173 if ( mFrequencyStepSize < ONE_HUNDRED_KHZ ) { |
|
174 mFrequencyStepSize = ONE_HUNDRED_KHZ; |
|
175 } |
|
176 |
46 |
177 RadioStationModel* stationModel = &mUiEngine->stationModel(); |
47 RadioStationModel* stationModel = &mUiEngine->stationModel(); |
178 Radio::connect( stationModel, SIGNAL(rowsInserted(QModelIndex,int,int)), |
48 Radio::connect( stationModel, SIGNAL(rowsInserted(QModelIndex,int,int)), |
179 this, SLOT(updateStation(QModelIndex,int,int)) ); |
49 this, SLOT(updateStation(QModelIndex,int,int)) ); |
180 Radio::connect( stationModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), |
50 Radio::connect( stationModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), |
181 this, SLOT(removeStation(QModelIndex,int,int)) ); |
51 this, SLOT(removeStation(QModelIndex,int,int)) ); |
182 Radio::connect( stationModel, SIGNAL(modelReset()), |
52 Radio::connect( stationModel, SIGNAL(modelReset()), |
183 this, SLOT(initEmptyItems()) ); |
53 this, SLOT(initEmptyItems()) ); |
184 |
|
185 updateAllItems(); |
|
186 |
|
187 showButtons(); |
|
188 } |
54 } |
189 |
55 |
190 /*! |
56 /*! |
191 * |
57 * |
192 */ |
58 */ |
193 void RadioFrequencyStrip::setFrequency( const uint frequency, int reason, Scroll::Direction direction ) |
59 void RadioFrequencyStrip::setFrequency( const uint newFrequency, int reason, Scroll::Direction direction ) |
194 { |
60 { |
195 Q_UNUSED( reason ); |
61 Q_UNUSED( reason ); |
196 LOG_FORMAT( "RadioFrequencyStrip::setFrequency, frequency: %d, reason: %d", frequency, reason ); |
62 if ( newFrequency != frequency() || reason == TuneReason::Skip ) { |
197 if ( mFrequencies.contains( frequency ) ) { |
63 RadioFrequencyStripBase::setFrequency( newFrequency, reason, direction ); |
198 if ( frequency != mFrequency || reason == TuneReason::Skip ) { |
|
199 scrollToFrequency( frequency, direction, mAutoScrollTime, RadioUtil::tuneReason( reason ) ); |
|
200 } |
|
201 } |
|
202 } |
|
203 |
|
204 /*! |
|
205 * |
|
206 */ |
|
207 uint RadioFrequencyStrip::frequency() const |
|
208 { |
|
209 return mFrequency; |
|
210 } |
|
211 |
|
212 /*! |
|
213 * |
|
214 */ |
|
215 bool RadioFrequencyStrip::isInManualSeekMode() const |
|
216 { |
|
217 return mManualSeekMode; |
|
218 } |
|
219 |
|
220 /*! |
|
221 * |
|
222 */ |
|
223 void RadioFrequencyStrip::cancelManualSeek() |
|
224 { |
|
225 mManualSeekTimer->stop(); |
|
226 if ( mManualSeekMode ) { |
|
227 toggleManualSeek(); |
|
228 } |
|
229 } |
|
230 |
|
231 /*! |
|
232 * |
|
233 */ |
|
234 void RadioFrequencyStrip::addScannedStation( const RadioStation& station ) |
|
235 { |
|
236 FrequencyPos pos = mFrequencies.value( station.frequency() ); |
|
237 updateItem( pos.mItem, station.frequency() ); |
|
238 } |
|
239 |
|
240 /*! |
|
241 * |
|
242 */ |
|
243 void RadioFrequencyStrip::updateFavorite( const RadioStation& station ) |
|
244 { |
|
245 LOG_SLOT_CALLER; |
|
246 FrequencyPos pos = mFrequencies.value( station.frequency() ); |
|
247 updateItem( pos.mItem ); |
|
248 } |
|
249 |
|
250 /*! |
|
251 * Public slot |
|
252 * |
|
253 */ |
|
254 void RadioFrequencyStrip::setScanningMode( bool isScanning ) |
|
255 { |
|
256 mManualSeekTimer->stop(); |
|
257 if ( isScanning ) { |
|
258 initEmptyItems(); |
|
259 hideButtons(); |
|
260 scrollToFrequency( mMinFrequency, Scroll::Shortest, mAutoScrollTime ); |
|
261 } else { |
|
262 showButtons(); |
|
263 } |
|
264 setEnabled( !isScanning ); |
|
265 } |
|
266 |
|
267 /*! |
|
268 * Private slot |
|
269 * |
|
270 */ |
|
271 void RadioFrequencyStrip::removeStation( const QModelIndex& parent, int first, int last ) |
|
272 { |
|
273 Q_UNUSED( parent ); |
|
274 updateStationsInRange( first, last, true ); |
|
275 } |
|
276 |
|
277 /*! |
|
278 * Private slot |
|
279 * |
|
280 */ |
|
281 void RadioFrequencyStrip::updateStation( const QModelIndex& parent, int first, int last ) |
|
282 { |
|
283 Q_UNUSED( parent ); |
|
284 updateStationsInRange( first, last ); |
|
285 } |
|
286 |
|
287 /*! |
|
288 * Private slot |
|
289 * |
|
290 */ |
|
291 void RadioFrequencyStrip::initEmptyItems() |
|
292 { |
|
293 LOG_METHOD; |
|
294 //TODO: Remove the weird hack of checking the sender |
|
295 if ( !sender() || RadioUtil::scanStatus() != Scan::ScanningInMainView ) { |
|
296 QList<RadioStation> emptyList; |
|
297 foreach ( RadioFrequencyItem* item, mFrequencyItems ) { |
|
298 QPixmap pixmap = drawPixmap( item->frequency(), emptyList, item ); |
|
299 item->setPixmap( pixmap ); |
|
300 } |
|
301 } |
|
302 } |
|
303 |
|
304 /*! |
|
305 * Private slot |
|
306 */ |
|
307 void RadioFrequencyStrip::handleLeftButton() |
|
308 { |
|
309 emit skipRequested( StationSkip::PreviousFavorite ); |
|
310 } |
|
311 |
|
312 /*! |
|
313 * Private slot |
|
314 */ |
|
315 void RadioFrequencyStrip::handleLongLeftButton() |
|
316 { |
|
317 emit seekRequested( Seek::Down ); |
|
318 } |
|
319 |
|
320 /*! |
|
321 * Private slot |
|
322 */ |
|
323 void RadioFrequencyStrip::handleRightButton() |
|
324 { |
|
325 emit skipRequested( StationSkip::NextFavorite ); |
|
326 } |
|
327 |
|
328 /*! |
|
329 * Private slot |
|
330 */ |
|
331 void RadioFrequencyStrip::handleLongRightButton() |
|
332 { |
|
333 emit seekRequested( Seek::Up ); |
|
334 } |
|
335 |
|
336 /*! |
|
337 * Private slot |
|
338 * |
|
339 */ |
|
340 void RadioFrequencyStrip::toggleManualSeek() |
|
341 { |
|
342 mManualSeekMode = !mManualSeekMode; |
|
343 emit manualSeekChanged( mManualSeekMode ); |
|
344 |
|
345 if ( mManualSeekMode ) { |
|
346 grabMouse(); |
|
347 hideButtons(); |
|
348 mManualSeekTimerId = startTimer( MANUALSEEK_SIGNAL_DELAY ); |
|
349 } else { |
|
350 ungrabMouse(); |
|
351 showButtons(); |
|
352 killTimer( mManualSeekTimerId ); |
|
353 mManualSeekTimerId = 0; |
|
354 } |
|
355 } |
|
356 |
|
357 /*! |
|
358 * Private slot |
|
359 */ |
|
360 void RadioFrequencyStrip::handleScrollingEnd() |
|
361 { |
|
362 // Check if the selector is in the invalid area where the strip loops around |
|
363 const int selectorPosition = selectorPos(); |
|
364 if ( mManualSeekMode ) { |
|
365 if ( !mPositions.contains( selectorPosition ) ) { |
|
366 if ( selectorPosition < mMaxWidth - ITEM_WIDTH + mSeparatorPos ) { |
|
367 scrollToFrequency( mMaxFrequency, Scroll::Shortest, 500 ); |
|
368 emit frequencyChanged( mMaxFrequency, TuneReason::ManualSeekUpdate, Scroll::Shortest ); |
|
369 } else { |
|
370 scrollToFrequency( mMinFrequency, Scroll::Shortest, 500 ); |
|
371 emit frequencyChanged( mMinFrequency, TuneReason::ManualSeekUpdate, Scroll::Shortest ); |
|
372 } |
|
373 } |
|
374 |
|
375 mManualSeekTimer->start( MANUALSEEK_END_TIMEOUT ); |
|
376 } |
64 } |
377 } |
65 } |
378 |
66 |
379 /*! |
67 /*! |
380 * \reimp |
68 * \reimp |
381 */ |
69 */ |
382 void RadioFrequencyStrip::updateItemPrimitive( QGraphicsItem* itemToUpdate, int itemIndex ) |
70 bool RadioFrequencyStrip::isInitialized() const |
383 { |
71 { |
384 QGraphicsPixmapItem* item = static_cast<QGraphicsPixmapItem*>( itemToUpdate ); |
72 return mUiEngine != NULL; |
385 if ( itemIndex < mFrequencyItems.count() ) { |
|
386 item->setPixmap( mFrequencyItems.at( itemIndex )->updatePrimitive( item ) ); |
|
387 } |
|
388 } |
73 } |
389 |
74 |
390 /*! |
75 /*! |
391 * \reimp |
76 * \reimp |
392 */ |
77 */ |
393 QGraphicsItem* RadioFrequencyStrip::createItemPrimitive( QGraphicsItem* parent ) |
78 QList<FrequencyStrip::StationMarker> RadioFrequencyStrip::stationsInRange( uint minFrequency, uint maxFrequency ) const |
394 { |
79 { |
395 return new QGraphicsPixmapItem( parent ); |
80 QList<RadioStation> stations = mUiEngine->stationsInRange( minFrequency, maxFrequency ); |
|
81 QList<FrequencyStrip::StationMarker> markers; |
|
82 foreach ( const RadioStation& station, stations ) { |
|
83 markers.append( FrequencyStrip::StationMarker( station.frequency(), station.isFavorite() ) ); |
|
84 } |
|
85 return markers; |
396 } |
86 } |
397 |
87 |
398 /*! |
88 /*! |
399 * \reimp |
89 * \reimp |
400 */ |
90 */ |
401 void RadioFrequencyStrip::scrollPosChanged() |
91 void RadioFrequencyStrip::emitFrequencyChanged( uint frequency, int reason, int direction ) |
402 { |
92 { |
403 if ( mManualSeekMode ) { |
93 int tuneReason = TuneReason::Unspecified; |
404 const int pos = selectorPos(); |
94 if ( reason == FrequencyStrip::ManualSeekUpdate ) { |
405 const uint frequency = mPositions.value( pos ); |
95 tuneReason = TuneReason::ManualSeekUpdate; |
406 if ( frequency > 0 ) { |
96 } else if ( reason == FrequencyStrip::ManualSeekTune ) { |
407 mFrequency = mPositions.value( pos ); |
97 tuneReason = TuneReason::ManualSeekTune; |
408 emit frequencyChanged( mFrequency, TuneReason::ManualSeekUpdate, Scroll::Shortest ); |
|
409 } |
|
410 } |
98 } |
|
99 |
|
100 emit frequencyChanged( frequency, tuneReason, direction ); |
|
101 } |
|
102 |
|
103 /*! |
|
104 * |
|
105 */ |
|
106 void RadioFrequencyStrip::skipToPrevious() |
|
107 { |
|
108 emit skipRequested( StationSkip::Previous ); |
|
109 } |
|
110 |
|
111 /*! |
|
112 * |
|
113 */ |
|
114 void RadioFrequencyStrip::skipToPreviousFavorite() |
|
115 { |
|
116 emit skipRequested( StationSkip::PreviousFavorite ); |
|
117 } |
|
118 |
|
119 /*! |
|
120 * |
|
121 */ |
|
122 void RadioFrequencyStrip::skipToNext() |
|
123 { |
|
124 emit skipRequested( StationSkip::Next ); |
|
125 } |
|
126 |
|
127 /*! |
|
128 * |
|
129 */ |
|
130 void RadioFrequencyStrip::skipToNextFavorite() |
|
131 { |
|
132 emit skipRequested( StationSkip::NextFavorite ); |
|
133 } |
|
134 |
|
135 /*! |
|
136 * |
|
137 */ |
|
138 void RadioFrequencyStrip::seekDown() |
|
139 { |
|
140 emit seekRequested( Seek::Down ); |
|
141 } |
|
142 |
|
143 |
|
144 /*! |
|
145 * |
|
146 */ |
|
147 void RadioFrequencyStrip::seekUp() |
|
148 { |
|
149 emit seekRequested( Seek::Up ); |
411 } |
150 } |
412 |
151 |
413 /*! |
152 /*! |
414 * \reimp |
153 * \reimp |
415 */ |
154 */ |
416 void RadioFrequencyStrip::resizeEvent ( QGraphicsSceneResizeEvent* event ) |
155 bool RadioFrequencyStrip::isScanning() const |
417 { |
156 { |
418 LOG_METHOD; |
157 return RadioUtil::scanStatus() == Scan::ScanningInMainView; |
419 RadioStripBase::resizeEvent( event ); |
|
420 |
|
421 initSelector(); |
|
422 |
|
423 const qreal height = event->newSize().height(); |
|
424 const qreal width = event->newSize().width(); |
|
425 |
|
426 mSelectorPos = width / 2; |
|
427 mSelectorImage->setOffset( mSelectorPos - (INDICATOR_WIDTH / 2), 0.0 ); |
|
428 |
|
429 if ( mLeftButton && mRightButton ) { |
|
430 mLeftButton->resize( height, height ); |
|
431 mRightButton->resize( height, height ); |
|
432 mRightButton->setPos( QPointF( width - height, 0 ) ); |
|
433 } |
|
434 |
|
435 scrollToFrequency( mFrequency ); |
|
436 } |
158 } |
437 |
159 |
438 /*! |
160 /*! |
439 * \reimp |
161 * \reimp |
440 */ |
162 */ |
441 //void RadioFrequencyStrip::showEvent( QShowEvent* event ) |
163 uint RadioFrequencyStrip::frequencyAtIndex( int index ) const |
442 //{ |
|
443 // RadioStripBase::showEvent( event ); |
|
444 // scrollToFrequency( mFrequency ); |
|
445 //} |
|
446 |
|
447 /*! |
|
448 * \reimp |
|
449 */ |
|
450 void RadioFrequencyStrip::changeEvent( QEvent* event ) |
|
451 { |
164 { |
452 if ( event->type() == HbEvent::ThemeChanged ) { |
165 RadioStationModel& model = mUiEngine->stationModel(); |
453 // Update the foreground color and redraw each item |
166 return model.data( model.index( index, 0, QModelIndex() ), |
454 mForegroundColor = Qt::white;// HbColorScheme::color( TEXT_COLOR_ATTRIBUTE ); |
167 RadioRole::RadioStationRole ).value<RadioStation>().frequency(); |
455 updateAllItems(); |
|
456 } |
|
457 |
|
458 return RadioStripBase::changeEvent(event); |
|
459 } |
168 } |
460 |
|
461 /*! |
|
462 * \reimp |
|
463 */ |
|
464 void RadioFrequencyStrip::mousePressEvent( QGraphicsSceneMouseEvent* event ) |
|
465 { |
|
466 RadioStripBase::mousePressEvent( event ); |
|
467 |
|
468 mManualSeekTimer->stop(); |
|
469 if ( mManualSeekMode ) { |
|
470 const bool insideStrip = rect().contains( event->pos() ); |
|
471 if ( !insideStrip ) { |
|
472 toggleManualSeek(); |
|
473 } |
|
474 } else { |
|
475 mManualSeekTimer->start( MANUALSEEK_START_TIMEOUT ); |
|
476 } |
|
477 } |
|
478 |
|
479 /*! |
|
480 * \reimp |
|
481 */ |
|
482 void RadioFrequencyStrip::mouseReleaseEvent( QGraphicsSceneMouseEvent* event ) |
|
483 { |
|
484 RadioStripBase::mouseReleaseEvent( event ); |
|
485 |
|
486 mManualSeekTimer->stop(); |
|
487 if ( mManualSeekMode && !isScrolling() ) { |
|
488 mManualSeekTimer->start( MANUALSEEK_END_TIMEOUT ); |
|
489 } |
|
490 } |
|
491 |
|
492 /*! |
|
493 * \reimp |
|
494 */ |
|
495 void RadioFrequencyStrip::gestureEvent( QGestureEvent* event ) |
|
496 { |
|
497 HbSwipeGesture* swipeGesture = static_cast<HbSwipeGesture*>( event->gesture( Qt::SwipeGesture ) ); |
|
498 if ( swipeGesture && !mManualSeekMode ) { |
|
499 if ( swipeGesture->state() == Qt::GestureFinished ) { |
|
500 if ( swipeGesture->horizontalDirection() == QSwipeGesture::Left ) { |
|
501 emit skipRequested( StationSkip::Next ); |
|
502 } else if ( swipeGesture->horizontalDirection() == QSwipeGesture::Right ) { |
|
503 emit skipRequested( StationSkip::Previous ); |
|
504 } |
|
505 } |
|
506 } else if ( mManualSeekMode ) { |
|
507 RadioStripBase::gestureEvent( event ); |
|
508 } |
|
509 } |
|
510 |
|
511 /*! |
|
512 * \reimp |
|
513 */ |
|
514 void RadioFrequencyStrip::timerEvent( QTimerEvent* event ) |
|
515 { |
|
516 Q_UNUSED( event ); |
|
517 if ( mLastReportedFrequency != mFrequency ) { |
|
518 mLastReportedFrequency = mFrequency; |
|
519 emit frequencyChanged( mFrequency, TuneReason::ManualSeekTune, Scroll::Shortest ); |
|
520 } |
|
521 } |
|
522 |
|
523 /*! |
|
524 * |
|
525 */ |
|
526 void RadioFrequencyStrip::initModel() |
|
527 { |
|
528 const uint minFreq = uint( qreal(mMinFrequency) / ONE_HERTZ + ROUNDER ); |
|
529 const uint maxFreq = uint( qreal(mMaxFrequency) / ONE_HERTZ + 0.9 ); // always round up |
|
530 |
|
531 QStringList list; |
|
532 QString freqText; |
|
533 for ( uint i = minFreq; i <= maxFreq; ++i ) { |
|
534 freqText = QString::number( i ); |
|
535 list.append( freqText ); |
|
536 mFrequencyItems.append( new RadioFrequencyItem( freqText ) ); |
|
537 } |
|
538 mFrequencyItems.append( new RadioFrequencyItem( "" ) ); |
|
539 list.append( "" ); |
|
540 |
|
541 mMaxWidth = list.count() * ITEM_WIDTH; |
|
542 |
|
543 mSeparatorPos = qreal(ITEM_WIDTH) / 2; |
|
544 const uint minDrawableFreq = minFreq * ONE_HERTZ - HALF_HERTZ;; |
|
545 const uint maxDrawableFreq = maxFreq * ONE_HERTZ + HALF_HERTZ; |
|
546 mSeparatorPos += qreal( ( mMinFrequency - minDrawableFreq ) / 2 ) / PIXEL_IN_HZ; |
|
547 mSeparatorPos -= qreal( ( maxDrawableFreq - mMaxFrequency ) / 2 ) / PIXEL_IN_HZ; |
|
548 |
|
549 setModel( new QStringListModel( list, this ) ); |
|
550 } |
|
551 |
|
552 /*! |
|
553 * |
|
554 */ |
|
555 void RadioFrequencyStrip::initSelector() |
|
556 { |
|
557 QPixmap selectorPixmap = QPixmap( QSize( SELECTOR_WIDTH, (int)size().height() ) ); |
|
558 selectorPixmap.fill( Qt::red ); |
|
559 mSelectorImage->setPixmap( selectorPixmap ); |
|
560 mSelectorImage->setZValue( SELECTOR_Z_POS ); |
|
561 } |
|
562 |
|
563 /*! |
|
564 * |
|
565 */ |
|
566 void RadioFrequencyStrip::initPositions() |
|
567 { |
|
568 int prevPos = 0; |
|
569 int nextPos = 0; |
|
570 const int lastPos = mFrequencies.value( mMaxFrequency ).mPosition; |
|
571 for ( int i = mFrequencies.value( mMinFrequency ).mPosition; i < lastPos; ++i ) { |
|
572 if ( mPositions.contains( i ) ) { |
|
573 prevPos = i; |
|
574 const uint freq = mPositions.value( prevPos ) + mFrequencyStepSize; |
|
575 if ( mFrequencies.contains( freq ) ) { |
|
576 nextPos = mFrequencies.value( freq ).mPosition; |
|
577 } else { |
|
578 nextPos = prevPos; |
|
579 } |
|
580 } else { |
|
581 const int nearestHit = ( i - prevPos ) < ( nextPos - i ) ? prevPos : nextPos; |
|
582 mPositions.insert( i, mPositions.value( nearestHit ) ); |
|
583 } |
|
584 } |
|
585 } |
|
586 |
|
587 /*! |
|
588 * |
|
589 */ |
|
590 void RadioFrequencyStrip::initButtons() |
|
591 { |
|
592 mLeftButton->setZValue( SELECTOR_Z_POS ); |
|
593 mLeftButton->setObjectName( LEFT_BUTTON ); |
|
594 mRightButton->setZValue( SELECTOR_Z_POS ); |
|
595 mRightButton->setObjectName( RIGHT_BUTTON ); |
|
596 |
|
597 const qreal height = size().height(); |
|
598 const qreal width = size().width(); |
|
599 mLeftButton->resize( height, height ); |
|
600 mRightButton->resize( height, height ); |
|
601 mRightButton->setPos( QPointF( width - height, 0 ) ); |
|
602 |
|
603 QEffectList effectList; |
|
604 effectList.append( EffectInfo( mLeftButton, ":/effects/slide_to_left.fxml", SLIDE_TO_LEFT ) ); |
|
605 effectList.append( EffectInfo( mLeftButton, ":/effects/slide_from_left.fxml", SLIDE_FROM_LEFT ) ); |
|
606 effectList.append( EffectInfo( mRightButton, ":/effects/slide_to_right.fxml", SLIDE_TO_RIGHT ) ); |
|
607 effectList.append( EffectInfo( mRightButton, ":/effects/slide_from_right.fxml", SLIDE_FROM_RIGHT ) ); |
|
608 RadioUtil::addEffects( effectList ); |
|
609 } |
|
610 |
|
611 /*! |
|
612 * |
|
613 */ |
|
614 void RadioFrequencyStrip::addFrequencyPos( int pos, uint frequency, RadioFrequencyItem* item ) |
|
615 { |
|
616 mFrequencies.insert( frequency, FrequencyPos( pos, item ) ); |
|
617 mPositions.insert( pos, frequency ); |
|
618 } |
|
619 |
|
620 /*! |
|
621 * |
|
622 */ |
|
623 void RadioFrequencyStrip::updateStationsInRange( int first, int last, bool stationRemoved ) |
|
624 { |
|
625 if ( RadioUtil::scanStatus() != Scan::ScanningInMainView ) { |
|
626 RadioStationModel& model = mUiEngine->stationModel(); |
|
627 uint frequency = 0; |
|
628 for ( int i = first; i <= last; ++i ) { |
|
629 frequency = model.data( model.index( i, 0, QModelIndex() ), |
|
630 RadioRole::RadioStationRole ).value<RadioStation>().frequency(); |
|
631 if ( mFrequencies.contains( frequency ) ) { |
|
632 FrequencyPos pos = mFrequencies.value( frequency ); |
|
633 updateItem( pos.mItem, 0, stationRemoved ? frequency : 0 ); |
|
634 } |
|
635 } |
|
636 } |
|
637 } |
|
638 |
|
639 /*! |
|
640 * |
|
641 */ |
|
642 void RadioFrequencyStrip::updateItem( RadioFrequencyItem* item, uint upperRange, uint ignoredFrequency ) |
|
643 { |
|
644 if ( item ) { |
|
645 uint frequency = item->frequency(); |
|
646 QList<RadioStation> stations; |
|
647 |
|
648 if ( upperRange == 0 ) { |
|
649 upperRange = frequency + HALF_HERTZ; |
|
650 } |
|
651 |
|
652 if ( mUiEngine ) { |
|
653 stations = mUiEngine->stationsInRange( frequency - HALF_HERTZ, upperRange ); |
|
654 for ( int i = stations.count() - 1; ignoredFrequency > 0 && i >= 0; --i ) { |
|
655 if ( stations[i].frequency() == ignoredFrequency ) { |
|
656 stations.removeAt( i ); |
|
657 break; |
|
658 } |
|
659 } |
|
660 } |
|
661 |
|
662 QPixmap pixmap = drawPixmap( frequency, stations, item ); |
|
663 item->setPixmap( pixmap ); |
|
664 |
|
665 foreach ( const RadioStation& station, stations ) { |
|
666 frequency = station.frequency(); |
|
667 FrequencyPos pos = mFrequencies.value( frequency ); |
|
668 mFrequencies.insert( frequency, pos ); |
|
669 } |
|
670 } |
|
671 } |
|
672 |
|
673 /*! |
|
674 * |
|
675 */ |
|
676 void RadioFrequencyStrip::updateAllItems() |
|
677 { |
|
678 foreach ( RadioFrequencyItem* item, mFrequencyItems ) { |
|
679 updateItem( item ); |
|
680 } |
|
681 } |
|
682 |
|
683 /*! |
|
684 * |
|
685 */ |
|
686 QPixmap RadioFrequencyStrip::drawPixmap( uint frequency, QList<RadioStation> stations, RadioFrequencyItem* item ) |
|
687 { |
|
688 QPixmap pixmap( PIXMAP_WIDTH, mItemHeight ); |
|
689 pixmap.fill( Qt::transparent ); |
|
690 QPainter painter( &pixmap ); |
|
691 QPen normalPen = painter.pen(); |
|
692 QPen favoritePen = normalPen; |
|
693 normalPen.setColor( mForegroundColor ); |
|
694 painter.setPen( normalPen ); |
|
695 |
|
696 if ( frequency == 0 ) { |
|
697 painter.drawLine( makeTab( mSeparatorPos - 1 + ROUNDER, mItemHeight ) ); |
|
698 painter.drawLine( makeTab( mSeparatorPos + ROUNDER, mItemHeight ) ); |
|
699 return pixmap; |
|
700 } |
|
701 |
|
702 const QString itemText = QString::number( frequency / ONE_HERTZ ); |
|
703 const uint startFrequency = frequency - HALF_HERTZ; |
|
704 const uint endFrequency = startFrequency + ONE_HERTZ; |
|
705 const uint roundedMin = int( qreal(mMinFrequency) / ONE_HERTZ + ROUNDER ); |
|
706 const uint freq = frequency / ONE_HERTZ; |
|
707 const int diff = freq - roundedMin; |
|
708 const qreal startPixel = diff * ITEM_WIDTH; |
|
709 qreal pixels = 0.0; |
|
710 const qreal leftOverlap = PIXMAP_OVERLAP / 2; |
|
711 |
|
712 for ( uint frequency = startFrequency; frequency <= endFrequency; frequency += mFrequencyStepSize ) { |
|
713 |
|
714 if ( frequency < mMinFrequency || frequency > mMaxFrequency ) { |
|
715 continue; |
|
716 } |
|
717 |
|
718 pixels = qreal( frequency - startFrequency ) / PIXEL_IN_HZ; |
|
719 if ( frequency % ONE_HERTZ == 0 ) { |
|
720 |
|
721 // Draw the high frequency tab and the frequency text for the even number |
|
722 normalPen.setWidth( 3 ); |
|
723 painter.setPen( normalPen ); |
|
724 painter.drawLine( makeTab( pixels + leftOverlap - 1, TAB_HEIGHT_BIG ) ); |
|
725 normalPen.setWidth( 1 ); |
|
726 painter.setPen( normalPen ); |
|
727 |
|
728 // Draw the frequency text and its 00 decimals |
|
729 painter.setFont( DECIMAL_FONT ); |
|
730 const int decimalWidth = painter.fontMetrics().width( DECIMAL_TEXT ); |
|
731 const int decimalSpace = painter.fontMetrics().leftBearing( '.' ); |
|
732 painter.setFont( FREQUENCY_FONT ); |
|
733 const int frequencyWidth = painter.fontMetrics().width( itemText ); |
|
734 const int textPosX = int( pixels + leftOverlap - ( frequencyWidth + decimalSpace + decimalWidth ) / 2 ); |
|
735 painter.drawText( QPoint( textPosX, 20 ), itemText ); |
|
736 painter.setFont( DECIMAL_FONT ); |
|
737 painter.drawText( QPoint( textPosX + frequencyWidth + decimalSpace, 20 ), DECIMAL_TEXT ); |
|
738 |
|
739 } else if ( frequency % ONE_TAB_IN_HZ == 0 ) { |
|
740 |
|
741 // Draw the low frequency tab for the uneven number |
|
742 painter.drawLine( makeTab( pixels + leftOverlap, TAB_HEIGHT_SMALL ) ); |
|
743 |
|
744 } |
|
745 |
|
746 addFrequencyPos( int( startPixel + pixels + ROUNDER ), frequency, item ); |
|
747 } |
|
748 |
|
749 // Draw favorites and local stations |
|
750 favoritePen.setColor( Qt::yellow ); |
|
751 |
|
752 const int markerYPos = mItemHeight - 28; |
|
753 foreach ( const RadioStation& station, stations ) { |
|
754 const uint frequency = station.frequency(); |
|
755 pixels = qreal( frequency - startFrequency ) / PIXEL_IN_HZ; |
|
756 |
|
757 if ( station.isFavorite() ) { |
|
758 favoritePen.setWidth( PEN_WIDTH_FAVORITE ); |
|
759 painter.setPen( favoritePen ); |
|
760 painter.drawEllipse( int( pixels + leftOverlap - 3 ), markerYPos - 3, 6, 6 ); |
|
761 } else if ( station.isType( RadioStation::LocalStation ) ) { |
|
762 |
|
763 favoritePen.setWidth( 1 ); |
|
764 painter.setPen( favoritePen ); |
|
765 painter.drawEllipse( int( pixels + leftOverlap - 4 ), markerYPos - 4, 8, 8 ); |
|
766 } |
|
767 } |
|
768 |
|
769 return pixmap; |
|
770 } |
|
771 |
|
772 /*! |
|
773 * |
|
774 */ |
|
775 QLineF RadioFrequencyStrip::makeTab( qreal pos, int height ) |
|
776 { |
|
777 return QLineF( pos, mItemHeight - height, pos, mItemHeight ); |
|
778 } |
|
779 |
|
780 /*! |
|
781 * |
|
782 */ |
|
783 void RadioFrequencyStrip::emitFrequencyChanged( uint frequency ) |
|
784 { |
|
785 if ( frequency > 0 && frequency != mFrequency ) { |
|
786 mFrequency = frequency; |
|
787 //TOD: Get direction |
|
788 emit frequencyChanged( frequency, TuneReason::FrequencyStrip, Scroll::Shortest ); |
|
789 } |
|
790 } |
|
791 |
|
792 /*! |
|
793 * |
|
794 */ |
|
795 int RadioFrequencyStrip::selectorPos() const |
|
796 { |
|
797 const int pos = int( -contentWidget()->x() + mSelectorPos + ROUNDER ); |
|
798 return pos % mMaxWidth; |
|
799 } |
|
800 |
|
801 /*! |
|
802 * |
|
803 */ |
|
804 void RadioFrequencyStrip::scrollToFrequency( uint frequency, Scroll::Direction direction, int time, TuneReason::Reason reason ) |
|
805 { |
|
806 int targetFreqPos = mFrequencies.value( frequency ).mPosition; |
|
807 const int currentFreqPos = mFrequencies.value( mFrequency ).mPosition; |
|
808 const int currentPos = int( -contentWidget()->x() + mSelectorPos + ROUNDER ); |
|
809 const bool isInSecondHalf = currentPos >= mMaxWidth - ITEM_WIDTH + mSeparatorPos; |
|
810 |
|
811 // Special case: When there is only one favorite and the user presses skip |
|
812 // the strip must scroll around to the same frequency. |
|
813 if ( mFrequency == frequency && reason == TuneReason::Skip ) { |
|
814 if ( direction == Scroll::Left ) { |
|
815 targetFreqPos += mMaxWidth; |
|
816 } else { |
|
817 targetFreqPos -= mMaxWidth; |
|
818 } |
|
819 } |
|
820 |
|
821 mFrequency = frequency; |
|
822 |
|
823 qreal newPos = targetFreqPos; |
|
824 if ( direction == Scroll::Left ) { |
|
825 |
|
826 if ( currentFreqPos > targetFreqPos ) { |
|
827 newPos += mMaxWidth; |
|
828 } |
|
829 |
|
830 } else if ( direction == Scroll::Right ) { |
|
831 |
|
832 if ( currentFreqPos < targetFreqPos ) { |
|
833 newPos -= mMaxWidth; |
|
834 } |
|
835 |
|
836 } |
|
837 |
|
838 if ( isInSecondHalf ) { |
|
839 newPos += mMaxWidth; |
|
840 } |
|
841 |
|
842 newPos -= mSelectorPos - ROUNDER; |
|
843 |
|
844 // scrollContentsTo( QPointF( newPos, 0 ), time ); |
|
845 // TODO: Remove this and uncomment the above line. This is a temporary workaround to get the strip to move |
|
846 scrollContentsTo( QPointF( newPos, 0 ), 0 ); |
|
847 } |
|
848 |
|
849 /*! |
|
850 * |
|
851 */ |
|
852 void RadioFrequencyStrip::hideButtons() |
|
853 { |
|
854 HbEffect::start( mLeftButton, SLIDE_TO_LEFT ); |
|
855 HbEffect::start( mRightButton, SLIDE_TO_RIGHT ); |
|
856 } |
|
857 |
|
858 /*! |
|
859 * |
|
860 */ |
|
861 void RadioFrequencyStrip::showButtons() |
|
862 { |
|
863 HbEffect::start( mLeftButton, SLIDE_FROM_LEFT ); |
|
864 HbEffect::start( mRightButton, SLIDE_FROM_RIGHT ); |
|
865 } |
|