23 #include <HbPushButton> |
23 #include <HbPushButton> |
24 #include <QTimer> |
24 #include <QTimer> |
25 #include <HbColorScheme> |
25 #include <HbColorScheme> |
26 #include <HbEvent> |
26 #include <HbEvent> |
27 #include <HbSwipeGesture> |
27 #include <HbSwipeGesture> |
|
28 #include <HbDeviceProfile> |
28 |
29 |
29 #include "radiofrequencystrip.h" |
30 #include "radiofrequencystrip.h" |
30 #include "radiofrequencyitem.h" |
31 #include "radiofrequencyitem.h" |
31 #include "radiouiengine.h" |
32 #include "radiouiengine.h" |
32 #include "radiostation.h" |
33 #include "radiostation.h" |
33 #include "radiostationmodel.h" |
34 #include "radiostationmodel.h" |
34 #include "radiouiutilities.h" |
35 #include "radioutil.h" |
|
36 #include "radiouiloader.h" |
35 #include "radiologger.h" |
37 #include "radiologger.h" |
36 |
38 |
37 // Frequency lines |
39 // Frequency lines |
38 const int KTabHeightSmall = 10; |
40 const int TAB_HEIGHT_SMALL = 12; |
39 const int KTabHeightBig = 15; |
41 const int TAB_HEIGHT_BIG = 18; |
40 const int KTabWidthFavorite = 4; |
42 const int PEN_WIDTH_FAVORITE = 4; |
41 const qreal KIndicatorWidth = 2.0; |
43 const qreal INDICATOR_WIDTH = 2.0; |
42 |
44 |
43 const qreal KRounder = 0.5; |
45 const qreal ROUNDER = 0.5; |
44 const int KSelectorWidth = 2; |
46 const int SELECTOR_WIDTH = 2; |
45 const int KSelectorZPos = 100; |
47 const int SELECTOR_Z_POS = 100; |
46 |
48 |
47 const int KHalfHertz = KOneHertz / 2; |
49 const int HALF_HERTZ = ONE_HERTZ / 2; |
48 const int KOneTabDistance = 15; |
50 const int ONE_TAB_DISTANCE = 20; |
49 const uint KOneTabInHz = 0.2 * KOneHertz; |
51 const uint ONE_TAB_IN_HZ = uint( 0.2 * ONE_HERTZ ); |
50 const qreal KPixelInHz = KOneTabInHz / KOneTabDistance; |
52 const qreal PIXEL_IN_HZ = ONE_TAB_IN_HZ / ONE_TAB_DISTANCE; |
51 const int KWidth = KOneTabDistance * 5; |
53 const qreal PIXMAP_OVERLAP = qreal( ONE_TAB_DISTANCE ) / 2; |
52 //const int KPixmapWidth = KWidth + KOneTabDistance; |
54 const int ITEM_WIDTH = ONE_TAB_DISTANCE * 5; |
53 const int KHeight = 50; //TODO: Remove hardcoding |
55 const int PIXMAP_WIDTH = ITEM_WIDTH + (int)PIXMAP_OVERLAP; |
54 |
56 |
55 const int K100Khz = 100000; |
57 const uint ONE_HUNDRED_KHZ = 100000; |
56 |
58 |
57 const char* KSlideToLeft = "SlideToLeft"; |
59 const char* DECIMAL_TEXT = ".0"; |
58 const char* KSlideFromLeft = "SlideFromLeft"; |
60 |
59 const char* KSlideToRight = "SlideToRight"; |
61 #ifdef BUILD_WIN32 |
60 const char* KSlideFromRight = "SlideFromRight"; |
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"; |
61 const char* LEFT_BUTTON = "tv:left_button"; |
76 const char* LEFT_BUTTON = "tv:left_button"; |
62 const char* RIGHT_BUTTON = "tv:right_button"; |
77 const char* RIGHT_BUTTON = "tv:right_button"; |
63 |
78 |
64 const char* TEXT_COLOR_ATTRIBUTE = "text"; |
79 const char* TEXT_COLOR_ATTRIBUTE = "text"; |
65 const int BUTTON_HIDE_TIMEOUT = 500; |
80 const int MANUALSEEK_START_TIMEOUT = 400; |
66 const int BUTTON_SHOW_TIMEOUT = 1000; |
81 const int MANUALSEEK_END_TIMEOUT = 2000; |
67 |
82 const int MANUALSEEK_SIGNAL_DELAY = 300; |
68 /*! |
|
69 * |
|
70 */ |
|
71 static QLineF makeTab( qreal pos, int height ) |
|
72 { |
|
73 return QLineF( pos, KHeight - height, pos, KHeight ); |
|
74 } |
|
75 |
83 |
76 /*! |
84 /*! |
77 * |
85 * |
78 */ |
86 */ |
79 RadioFrequencyStrip::RadioFrequencyStrip() : |
87 RadioFrequencyStrip::RadioFrequencyStrip() : |
80 RadioStripBase(), |
88 RadioStripBase(), |
81 mUiEngine( NULL ), |
89 mUiEngine( NULL ), |
|
90 mItemHeight( 8 ), |
82 mMinFrequency( 87500000 ), |
91 mMinFrequency( 87500000 ), |
83 mMaxFrequency( 108000000 ), |
92 mMaxFrequency( 108000000 ), |
84 mFrequencyStepSize( 100000 ), |
93 mFrequencyStepSize( 100000 ), |
85 mFrequency( 87500000 ), |
94 mFrequency( 87500000 ), |
86 mSelectorImage( new QGraphicsPixmapItem( this ) ), |
95 mSelectorImage( new QGraphicsPixmapItem( this ) ), |
87 mSeparatorPos( 0.0 ), |
96 mSeparatorPos( 0.0 ), |
88 mMaxWidth( 0 ), |
97 mMaxWidth( 0 ), |
89 mSelectorPos( 0.0 ), |
98 mSelectorPos( 0.0 ), |
90 mLeftButton( new HbPushButton( this ) ), |
99 mLeftButton( 0 ), |
91 mRightButton( new HbPushButton( this ) ), |
100 mRightButton( 0 ), |
92 mButtonTimer( NULL ), |
101 mManualSeekTimer( NULL ), |
93 mButtonsVisible( true ), |
102 mManualSeekMode( false ), |
94 mUserIsScrolling( false ), |
103 mLastReportedFrequency( 0 ), |
|
104 mManualSeekTimerId( 0 ), |
95 mForegroundColor( Qt::white )//HbColorScheme::color( TEXT_COLOR_ATTRIBUTE ) ) |
105 mForegroundColor( Qt::white )//HbColorScheme::color( TEXT_COLOR_ATTRIBUTE ) ) |
96 { |
106 { |
97 RadioUiUtilities::setFrequencyStrip( this ); |
107 RadioUtil::setFrequencyStrip( this ); |
98 |
108 |
99 setScrollingStyle( HbScrollArea::Pan ); |
109 setScrollingStyle( HbScrollArea::PanWithFollowOn ); |
100 setItemSize( QSizeF( KWidth, KHeight ) ); |
110 setItemSize( QSizeF( ITEM_WIDTH + PIXMAP_OVERLAP / 2, mItemHeight ) ); |
101 setFrictionEnabled( true ); |
111 setOverlap( PIXMAP_OVERLAP / 2 ); |
102 |
112 } |
103 initModel(); |
113 |
104 |
114 /*! |
105 initSelector(); |
115 * Property |
106 |
116 */ |
107 initButtons(); |
117 void RadioFrequencyStrip::setItemHeight( int itemHeight ) |
108 |
118 { |
109 initEmptyItems(); |
119 mItemHeight = itemHeight; |
110 |
120 } |
111 mFrequency = RadioUiEngine::lastTunedFrequency(); |
121 |
112 scrollToFrequency( mFrequency, 0 ); |
122 /*! |
113 } |
123 * Property |
114 |
124 */ |
115 /*! |
125 int RadioFrequencyStrip::itemHeight() const |
116 * |
126 { |
117 */ |
127 return mItemHeight; |
118 void RadioFrequencyStrip::setLeftButtonIcon( const HbIcon& leftButtonIcon ) |
128 } |
119 { |
129 |
120 mLeftButtonIcon = leftButtonIcon; |
130 /*! |
121 if ( mLeftButton ) { |
131 * |
122 mLeftButtonIcon.setColor( Qt::white ); |
132 */ |
123 mLeftButton->setIcon( mLeftButtonIcon ); |
133 void RadioFrequencyStrip::init( RadioUiEngine* engine, RadioUiLoader& uiLoader ) |
124 } |
|
125 } |
|
126 |
|
127 /*! |
|
128 * |
|
129 */ |
|
130 HbIcon RadioFrequencyStrip::leftButtonIcon() const |
|
131 { |
|
132 return mLeftButtonIcon; |
|
133 } |
|
134 |
|
135 /*! |
|
136 * |
|
137 */ |
|
138 void RadioFrequencyStrip::setRightButtonIcon( const HbIcon& rightButtonIcon ) |
|
139 { |
|
140 mRightButtonIcon = rightButtonIcon; |
|
141 if ( mRightButton ) { |
|
142 mRightButtonIcon.setColor( Qt::white ); |
|
143 mRightButton->setIcon( mRightButtonIcon ); |
|
144 } |
|
145 } |
|
146 |
|
147 /*! |
|
148 * |
|
149 */ |
|
150 HbIcon RadioFrequencyStrip::rightButtonIcon() const |
|
151 { |
|
152 return mRightButtonIcon; |
|
153 } |
|
154 |
|
155 /*! |
|
156 * |
|
157 */ |
|
158 void RadioFrequencyStrip::init( RadioUiEngine* engine ) |
|
159 { |
134 { |
160 mUiEngine = engine; |
135 mUiEngine = engine; |
161 mMinFrequency = mUiEngine->minFrequency(); |
136 mMinFrequency = mUiEngine->minFrequency(); |
162 mMaxFrequency = mUiEngine->maxFrequency(); |
137 mMaxFrequency = mUiEngine->maxFrequency(); |
163 mFrequencyStepSize = mUiEngine->frequencyStepSize(); |
138 mFrequencyStepSize = mUiEngine->frequencyStepSize(); |
164 mFrequency = mUiEngine->currentFrequency(); |
139 mFrequency = RadioUiEngine::lastTunedFrequency(); |
165 scrollToFrequency( mFrequency, 0 ); |
140 |
166 |
141 initModel(); |
167 mButtonTimer = new QTimer( this ); |
142 initEmptyItems(); |
168 mButtonTimer->setInterval( BUTTON_HIDE_TIMEOUT ); |
143 initPositions(); |
169 mButtonTimer->setSingleShot( true ); |
144 |
170 connectAndTest( mButtonTimer, SIGNAL(timeout()), |
145 HbDeviceProfile deviceProfile; |
171 this, SLOT(toggleButtons()) ); |
146 mItemHeight = static_cast<int>( mItemHeight * deviceProfile.unitValue() ); |
172 |
147 |
173 connectAndTest( mLeftButton, SIGNAL(clicked()), |
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()), |
174 this, SLOT(handleLeftButton()) ); |
159 this, SLOT(handleLeftButton()) ); |
175 connectAndTest( mRightButton, SIGNAL(clicked()), |
160 Radio::connect( mRightButton, SIGNAL(clicked()), |
176 this, SLOT(handleRightButton()) ); |
161 this, SLOT(handleRightButton()) ); |
177 connectAndTest( mLeftButton, SIGNAL(longPress(QPointF)), |
162 Radio::connect( mLeftButton, SIGNAL(longPress(QPointF)), |
178 this, SLOT(handleLongLeftButton()) ); |
163 this, SLOT(handleLongLeftButton()) ); |
179 connectAndTest( mRightButton, SIGNAL(longPress(QPointF)), |
164 Radio::connect( mRightButton, SIGNAL(longPress(QPointF)), |
180 this, SLOT(handleLongRightButton()) ); |
165 this, SLOT(handleLongRightButton()) ); |
181 |
166 |
182 connectAndTest( this, SIGNAL(scrollingEnded()), |
167 Radio::connect( this, SIGNAL(scrollingEnded()), |
183 this, SLOT(checkIllegalPos()) ); |
168 this, SLOT(handleScrollingEnd()) ); |
184 |
169 |
185 grabGesture( Qt::SwipeGesture ); |
170 grabGesture( Qt::SwipeGesture ); |
186 |
171 |
187 //TODO: Remove. Stepsize hardcoded to 100 Khz in europe region during demo |
172 //TODO: Remove. Stepsize hardcoded to 100 Khz in europe region during demo |
188 if ( mFrequencyStepSize < K100Khz ) { |
173 if ( mFrequencyStepSize < ONE_HUNDRED_KHZ ) { |
189 mFrequencyStepSize = K100Khz; |
174 mFrequencyStepSize = ONE_HUNDRED_KHZ; |
190 } |
175 } |
191 |
176 |
192 RadioStationModel* stationModel = &mUiEngine->stationModel(); |
177 RadioStationModel* stationModel = &mUiEngine->stationModel(); |
193 connectAndTest( stationModel, SIGNAL(rowsInserted(QModelIndex,int,int)), |
178 Radio::connect( stationModel, SIGNAL(rowsInserted(QModelIndex,int,int)), |
194 this, SLOT(updateStation(QModelIndex,int,int)) ); |
179 this, SLOT(updateStation(QModelIndex,int,int)) ); |
195 connectAndTest( stationModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), |
180 Radio::connect( stationModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), |
196 this, SLOT(updateStation(QModelIndex,int,int)) ); |
181 this, SLOT(removeStation(QModelIndex,int,int)) ); |
197 connectAndTest( stationModel, SIGNAL(modelReset()), |
182 Radio::connect( stationModel, SIGNAL(modelReset()), |
198 this, SLOT(initEmptyItems()) ); |
183 this, SLOT(initEmptyItems()) ); |
199 |
184 |
200 initPositions(); |
185 updateAllItems(); |
201 |
186 |
202 void updateItems(); |
187 showButtons(); |
203 } |
188 } |
204 |
189 |
205 /*! |
190 /*! |
206 * |
191 * |
207 */ |
192 */ |
208 void RadioFrequencyStrip::setFrequency( const uint frequency, int reason ) |
193 void RadioFrequencyStrip::setFrequency( const uint frequency, int reason, Scroll::Direction direction ) |
209 { |
194 { |
|
195 Q_UNUSED( reason ); |
210 LOG_FORMAT( "RadioFrequencyStrip::setFrequency, frequency: %d, reason: %d", frequency, reason ); |
196 LOG_FORMAT( "RadioFrequencyStrip::setFrequency, frequency: %d, reason: %d", frequency, reason ); |
211 if ( reason != TuneReason::FrequencyStrip && // Not sent by the FrequencyStrip |
197 if ( mFrequencies.contains( frequency ) ) { |
212 frequency != mFrequency && // Different from the current |
198 if ( frequency != mFrequency || reason == TuneReason::Skip ) { |
213 mFrequencies.contains( frequency ) ) // 0 frequency means any illegal value |
199 scrollToFrequency( frequency, direction, mAutoScrollTime, RadioUtil::tuneReason( reason ) ); |
214 { |
|
215 scrollToFrequency( frequency, mAutoScrollTime ); |
|
216 if ( reason != TuneReason::Skip && reason != TuneReason::StationScan ) { |
|
217 emitFrequencyChanged( frequency ); |
|
218 } |
200 } |
219 } |
201 } |
220 } |
202 } |
221 |
203 |
222 /*! |
204 /*! |
226 { |
208 { |
227 return mFrequency; |
209 return mFrequency; |
228 } |
210 } |
229 |
211 |
230 /*! |
212 /*! |
231 * Public slot |
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 /*! |
232 * |
241 * |
233 */ |
242 */ |
234 void RadioFrequencyStrip::updateFavorite( const RadioStation& station ) |
243 void RadioFrequencyStrip::updateFavorite( const RadioStation& station ) |
235 { |
244 { |
236 LOG_SLOT_CALLER; |
245 LOG_SLOT_CALLER; |
237 FrequencyPos pos = mFrequencies.value( station.frequency() ); |
246 FrequencyPos pos = mFrequencies.value( station.frequency() ); |
238 updateFavorites( pos.mItem ); |
247 updateItem( pos.mItem ); |
239 } |
248 } |
240 |
249 |
241 /*! |
250 /*! |
242 * Public slot |
251 * Public slot |
243 * |
252 * |
244 */ |
253 */ |
245 void RadioFrequencyStrip::setScanningMode( bool isScanning ) |
254 void RadioFrequencyStrip::setScanningMode( bool isScanning ) |
246 { |
255 { |
247 mButtonTimer->stop(); |
256 mManualSeekTimer->stop(); |
248 if ( isScanning ) { |
257 if ( isScanning ) { |
249 scrollToFrequency( mMinFrequency, mAutoScrollTime ); |
258 initEmptyItems(); |
250 hideButtons(); |
259 hideButtons(); |
|
260 scrollToFrequency( mMinFrequency, Scroll::Shortest, mAutoScrollTime ); |
251 } else { |
261 } else { |
252 showButtons(); |
262 showButtons(); |
253 |
|
254 } |
263 } |
255 setEnabled( !isScanning ); |
264 setEnabled( !isScanning ); |
256 } |
265 } |
257 |
266 |
258 /*! |
267 /*! |
259 * Private slot |
268 * Private slot |
260 * |
269 * |
261 */ |
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 */ |
262 void RadioFrequencyStrip::updateStation( const QModelIndex& parent, int first, int last ) |
281 void RadioFrequencyStrip::updateStation( const QModelIndex& parent, int first, int last ) |
263 { |
282 { |
264 Q_UNUSED( parent ); |
283 Q_UNUSED( parent ); |
265 RadioStationModel& model = mUiEngine->stationModel(); |
284 updateStationsInRange( first, last ); |
266 uint frequency = 0; |
|
267 for ( int i = first; i <= last; ++i ) { |
|
268 frequency = model.data( model.index( i, 0, QModelIndex() ), |
|
269 RadioStationModel::RadioStationRole ).value<RadioStation>().frequency(); |
|
270 if ( mFrequencies.contains( frequency ) ) { |
|
271 FrequencyPos pos = mFrequencies.value( frequency ); |
|
272 updateFavorites( pos.mItem ); |
|
273 } |
|
274 } |
|
275 } |
285 } |
276 |
286 |
277 /*! |
287 /*! |
278 * Private slot |
288 * Private slot |
279 * |
289 * |
280 */ |
290 */ |
281 void RadioFrequencyStrip::initEmptyItems() |
291 void RadioFrequencyStrip::initEmptyItems() |
282 { |
292 { |
283 LOG_METHOD; |
293 LOG_METHOD; |
284 QList<RadioStation> emptyList; |
294 //TODO: Remove the weird hack of checking the sender |
285 foreach ( RadioFrequencyItem* item, mFrequencyItems ) { |
295 if ( !sender() || RadioUtil::scanStatus() != Scan::ScanningInMainView ) { |
286 QPixmap pixmap = drawPixmap( item->frequency(), emptyList, item ); |
296 QList<RadioStation> emptyList; |
287 item->setPixmap( pixmap ); |
297 foreach ( RadioFrequencyItem* item, mFrequencyItems ) { |
|
298 QPixmap pixmap = drawPixmap( item->frequency(), emptyList, item ); |
|
299 item->setPixmap( pixmap ); |
|
300 } |
288 } |
301 } |
289 } |
302 } |
290 |
303 |
291 /*! |
304 /*! |
292 * Private slot |
305 * Private slot |
370 } |
396 } |
371 |
397 |
372 /*! |
398 /*! |
373 * \reimp |
399 * \reimp |
374 */ |
400 */ |
375 void RadioFrequencyStrip::scrollPosChanged( QPointF newPosition ) |
401 void RadioFrequencyStrip::scrollPosChanged() |
376 { |
402 { |
377 Q_UNUSED( newPosition ); |
403 if ( mManualSeekMode ) { |
378 |
|
379 if ( mUserIsScrolling ) { |
|
380 const int pos = selectorPos(); |
404 const int pos = selectorPos(); |
381 emitFrequencyChanged( mPositions.value( pos ) ); |
405 const uint frequency = mPositions.value( pos ); |
|
406 if ( frequency > 0 ) { |
|
407 mFrequency = mPositions.value( pos ); |
|
408 emit frequencyChanged( mFrequency, TuneReason::ManualSeekUpdate, Scroll::Shortest ); |
|
409 } |
382 } |
410 } |
383 } |
411 } |
384 |
412 |
385 /*! |
413 /*! |
386 * \reimp |
414 * \reimp |
387 */ |
415 */ |
388 void RadioFrequencyStrip::resizeEvent ( QGraphicsSceneResizeEvent* event ) |
416 void RadioFrequencyStrip::resizeEvent ( QGraphicsSceneResizeEvent* event ) |
389 { |
417 { |
390 LOG_METHOD_ENTER; |
418 LOG_METHOD; |
391 RadioStripBase::resizeEvent( event ); |
419 RadioStripBase::resizeEvent( event ); |
392 |
420 |
393 mSelectorPos = event->newSize().width() / 2; |
421 initSelector(); |
394 mSelectorImage->setOffset( mSelectorPos - (KIndicatorWidth / 2), 0.0 ); |
422 |
395 |
423 const qreal height = event->newSize().height(); |
396 const int stripHeight = event->newSize().height(); |
424 const qreal width = event->newSize().width(); |
397 if ( !mLeftButtonIcon.isNull() ) { |
425 |
398 mLeftButton->resize( stripHeight, stripHeight ); |
426 mSelectorPos = width / 2; |
399 mLeftButton->setBackground( mLeftButtonIcon ); |
427 mSelectorImage->setOffset( mSelectorPos - (INDICATOR_WIDTH / 2), 0.0 ); |
400 } |
428 |
401 |
429 if ( mLeftButton && mRightButton ) { |
402 if ( !mRightButtonIcon.isNull() ) { |
430 mLeftButton->resize( height, height ); |
403 mRightButton->resize( stripHeight, stripHeight ); |
431 mRightButton->resize( height, height ); |
404 mRightButton->setBackground( mRightButtonIcon ); |
432 mRightButton->setPos( QPointF( width - height, 0 ) ); |
405 } |
433 } |
406 mRightButton->setPos( QPointF( size().width() - mRightButton->size().width(), 0 ) ); |
434 |
407 |
435 scrollToFrequency( mFrequency ); |
408 scrollToFrequency( mFrequency, 0 ); |
436 } |
409 } |
437 |
410 |
438 /*! |
411 /*! |
439 * \reimp |
412 * \reimp |
440 */ |
413 */ |
441 //void RadioFrequencyStrip::showEvent( QShowEvent* event ) |
414 void RadioFrequencyStrip::showEvent( QShowEvent* event ) |
442 //{ |
415 { |
443 // RadioStripBase::showEvent( event ); |
416 Q_UNUSED( event ); |
444 // scrollToFrequency( mFrequency ); |
417 scrollToFrequency( mFrequency, 0 ); |
445 //} |
418 } |
|
419 |
446 |
420 /*! |
447 /*! |
421 * \reimp |
448 * \reimp |
422 */ |
449 */ |
423 void RadioFrequencyStrip::changeEvent( QEvent* event ) |
450 void RadioFrequencyStrip::changeEvent( QEvent* event ) |
424 { |
451 { |
425 if ( event->type() == HbEvent::ThemeChanged ) { |
452 if ( event->type() == HbEvent::ThemeChanged ) { |
426 // Update the foreground color and redraw each item |
453 // Update the foreground color and redraw each item |
427 mForegroundColor = Qt::white;// HbColorScheme::color( TEXT_COLOR_ATTRIBUTE ); |
454 mForegroundColor = Qt::white;// HbColorScheme::color( TEXT_COLOR_ATTRIBUTE ); |
428 updateItems(); |
455 updateAllItems(); |
429 } |
456 } |
430 |
457 |
431 return HbWidgetBase::changeEvent(event); |
458 return RadioStripBase::changeEvent(event); |
432 } |
459 } |
433 |
460 |
434 /*! |
461 /*! |
435 * \reimp |
462 * \reimp |
436 */ |
463 */ |
437 void RadioFrequencyStrip::mousePressEvent( QGraphicsSceneMouseEvent* event ) |
464 void RadioFrequencyStrip::mousePressEvent( QGraphicsSceneMouseEvent* event ) |
438 { |
465 { |
439 RadioStripBase::mousePressEvent( event ); |
466 RadioStripBase::mousePressEvent( event ); |
440 mUserIsScrolling = true; |
467 |
441 mButtonTimer->stop(); |
468 mManualSeekTimer->stop(); |
442 mButtonTimer->start( BUTTON_HIDE_TIMEOUT ); |
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 } |
443 } |
477 } |
444 |
478 |
445 /*! |
479 /*! |
446 * \reimp |
480 * \reimp |
447 */ |
481 */ |
448 void RadioFrequencyStrip::mouseReleaseEvent( QGraphicsSceneMouseEvent* event ) |
482 void RadioFrequencyStrip::mouseReleaseEvent( QGraphicsSceneMouseEvent* event ) |
449 { |
483 { |
450 mUserIsScrolling = false; |
|
451 RadioStripBase::mouseReleaseEvent( event ); |
484 RadioStripBase::mouseReleaseEvent( event ); |
452 |
485 |
453 // if ( !mIsPanGesture ) { |
486 mManualSeekTimer->stop(); |
454 // const qreal touchDelta = event->pos().x() - mSelectorPos; |
487 if ( mManualSeekMode && !isScrolling() ) { |
455 // const int touchPos = selectorPosition + touchDelta; |
488 mManualSeekTimer->start( MANUALSEEK_END_TIMEOUT ); |
456 // const uint frequencyAtPos = mPositions.value( touchPos ); |
|
457 // |
|
458 // uint foundFrequency = 0; |
|
459 // for ( int i = 0; i < 10; ++i ) { |
|
460 // const uint delta = i * mFrequencyStepSize; |
|
461 // FrequencyPos leftFreq = mFrequencies.value( frequencyAtPos - delta ); |
|
462 // FrequencyPos rightFreq = mFrequencies.value( frequencyAtPos + delta ); |
|
463 // |
|
464 // if ( touchPos - leftFreq.mPosition > KTouchPosThreshold ) { |
|
465 // break; |
|
466 // } |
|
467 // |
|
468 // if ( leftFreq.mFavorite || leftFreq.mLocalStation ) { |
|
469 // foundFrequency = frequencyAtPos - delta; |
|
470 // break; |
|
471 // } else if ( rightFreq.mFavorite || rightFreq.mLocalStation ) { |
|
472 // foundFrequency = frequencyAtPos + delta; |
|
473 // break; |
|
474 // } |
|
475 // } |
|
476 // |
|
477 // if ( foundFrequency > 0 ) { |
|
478 // setFrequency( foundFrequency, 0 ); |
|
479 // } |
|
480 // } |
|
481 |
|
482 mButtonTimer->stop(); |
|
483 if ( !mButtonsVisible ) { |
|
484 mButtonTimer->start( BUTTON_SHOW_TIMEOUT ); |
|
485 } |
489 } |
486 } |
490 } |
487 |
491 |
488 /*! |
492 /*! |
489 * \reimp |
493 * \reimp |
490 */ |
494 */ |
491 void RadioFrequencyStrip::gestureEvent( QGestureEvent* event ) |
495 void RadioFrequencyStrip::gestureEvent( QGestureEvent* event ) |
492 { |
496 { |
493 if ( HbSwipeGesture* gesture = static_cast<HbSwipeGesture*>( event->gesture( Qt::SwipeGesture ) ) ) { |
497 HbSwipeGesture* swipeGesture = static_cast<HbSwipeGesture*>( event->gesture( Qt::SwipeGesture ) ); |
494 if ( gesture->state() == Qt::GestureFinished ) { |
498 if ( swipeGesture && !mManualSeekMode ) { |
495 if ( gesture->horizontalDirection() == QSwipeGesture::Left ) { |
499 if ( swipeGesture->state() == Qt::GestureFinished ) { |
|
500 if ( swipeGesture->horizontalDirection() == QSwipeGesture::Left ) { |
496 emit skipRequested( StationSkip::Next ); |
501 emit skipRequested( StationSkip::Next ); |
497 } else if ( gesture->horizontalDirection() == QSwipeGesture::Right ) { |
502 } else if ( swipeGesture->horizontalDirection() == QSwipeGesture::Right ) { |
498 emit skipRequested( StationSkip::Previous ); |
503 emit skipRequested( StationSkip::Previous ); |
499 } |
504 } |
500 } |
505 } |
501 } else { |
506 } else if ( mManualSeekMode ) { |
502 RadioStripBase::gestureEvent( event ); |
507 RadioStripBase::gestureEvent( event ); |
503 } |
508 } |
504 } |
509 } |
505 |
510 |
506 /*! |
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 /*! |
507 * |
524 * |
508 */ |
525 */ |
509 void RadioFrequencyStrip::initModel() |
526 void RadioFrequencyStrip::initModel() |
510 { |
527 { |
511 const uint minFreq = uint( qreal(mMinFrequency) / KOneHertz + KRounder ); |
528 const uint minFreq = uint( qreal(mMinFrequency) / ONE_HERTZ + ROUNDER ); |
512 const uint maxFreq = uint( qreal(mMaxFrequency) / KOneHertz + 0.9 ); // always round up |
529 const uint maxFreq = uint( qreal(mMaxFrequency) / ONE_HERTZ + 0.9 ); // always round up |
513 |
530 |
514 QStringList list; |
531 QStringList list; |
515 QString freqText; |
532 QString freqText; |
516 for ( uint i = minFreq; i <= maxFreq; ++i ) { |
533 for ( uint i = minFreq; i <= maxFreq; ++i ) { |
517 freqText = QString::number( i ); |
534 freqText = QString::number( i ); |
618 } |
671 } |
619 |
672 |
620 /*! |
673 /*! |
621 * |
674 * |
622 */ |
675 */ |
623 void RadioFrequencyStrip::updateItems() |
676 void RadioFrequencyStrip::updateAllItems() |
624 { |
677 { |
625 foreach ( RadioFrequencyItem* item, mFrequencyItems ) { |
678 foreach ( RadioFrequencyItem* item, mFrequencyItems ) { |
626 updateFavorites( item ); |
679 updateItem( item ); |
627 } |
680 } |
628 } |
681 } |
629 |
682 |
630 /*! |
683 /*! |
631 * |
684 * |
632 */ |
685 */ |
633 QPixmap RadioFrequencyStrip::drawPixmap( uint frequency, QList<RadioStation> stations, RadioFrequencyItem* item ) |
686 QPixmap RadioFrequencyStrip::drawPixmap( uint frequency, QList<RadioStation> stations, RadioFrequencyItem* item ) |
634 { |
687 { |
635 QPixmap pixmap( KWidth, KHeight ); |
688 QPixmap pixmap( PIXMAP_WIDTH, mItemHeight ); |
636 pixmap.fill( Qt::transparent ); |
689 pixmap.fill( Qt::transparent ); |
637 QPainter painter( &pixmap ); |
690 QPainter painter( &pixmap ); |
638 QPen normalPen = painter.pen(); |
691 QPen normalPen = painter.pen(); |
639 QPen favoritePen = normalPen; |
692 QPen favoritePen = normalPen; |
640 normalPen.setColor( mForegroundColor ); |
693 normalPen.setColor( mForegroundColor ); |
641 painter.setPen( normalPen ); |
694 painter.setPen( normalPen ); |
642 |
695 |
643 if ( frequency == 0 ) { |
696 if ( frequency == 0 ) { |
644 painter.drawLine( makeTab( mSeparatorPos - 1 + KRounder, KHeight ) ); |
697 painter.drawLine( makeTab( mSeparatorPos - 1 + ROUNDER, mItemHeight ) ); |
645 painter.drawLine( makeTab( mSeparatorPos + KRounder, KHeight ) ); |
698 painter.drawLine( makeTab( mSeparatorPos + ROUNDER, mItemHeight ) ); |
646 return pixmap; |
699 return pixmap; |
647 } |
700 } |
648 |
701 |
649 const QString itemText = QString::number( frequency / KOneHertz ); |
702 const QString itemText = QString::number( frequency / ONE_HERTZ ); |
650 const uint startFrequency = frequency - KHalfHertz; |
703 const uint startFrequency = frequency - HALF_HERTZ; |
651 const uint endFrequency = startFrequency + KOneHertz; |
704 const uint endFrequency = startFrequency + ONE_HERTZ; |
652 const uint roundedMin = int( qreal(mMinFrequency) / KOneHertz + KRounder ); |
705 const uint roundedMin = int( qreal(mMinFrequency) / ONE_HERTZ + ROUNDER ); |
653 const uint freq = frequency / KOneHertz; |
706 const uint freq = frequency / ONE_HERTZ; |
654 const int diff = freq - roundedMin; |
707 const int diff = freq - roundedMin; |
655 const qreal startPixel = diff * KWidth; |
708 const qreal startPixel = diff * ITEM_WIDTH; |
656 qreal pixels = 0.0; |
709 qreal pixels = 0.0; |
657 QFont painterFont = painter.font(); |
710 const qreal leftOverlap = PIXMAP_OVERLAP / 2; |
658 painterFont.setPointSize( 6 ); |
711 |
659 painter.setFont( painterFont ); |
|
660 |
|
661 const int charWidth = painter.fontMetrics().averageCharWidth(); |
|
662 for ( uint frequency = startFrequency; frequency <= endFrequency; frequency += mFrequencyStepSize ) { |
712 for ( uint frequency = startFrequency; frequency <= endFrequency; frequency += mFrequencyStepSize ) { |
663 |
713 |
664 if ( frequency < mMinFrequency || frequency > mMaxFrequency ) { |
714 if ( frequency < mMinFrequency || frequency > mMaxFrequency ) { |
665 continue; |
715 continue; |
666 } |
716 } |
667 |
717 |
668 pixels = qreal( frequency - startFrequency ) / KPixelInHz; |
718 pixels = qreal( frequency - startFrequency ) / PIXEL_IN_HZ; |
669 if ( frequency % KOneHertz == 0 ) { |
719 if ( frequency % ONE_HERTZ == 0 ) { |
670 |
720 |
671 // Draw the high frequency tab and the frequency text for the even number |
721 // Draw the high frequency tab and the frequency text for the even number |
672 painter.drawLine( makeTab( pixels, KTabHeightBig ) ); |
722 normalPen.setWidth( 3 ); |
673 const int textPosX = pixels - itemText.length() * charWidth / 2; |
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 ); |
674 painter.drawText( QPoint( textPosX, 20 ), itemText ); |
735 painter.drawText( QPoint( textPosX, 20 ), itemText ); |
675 |
736 painter.setFont( DECIMAL_FONT ); |
676 } else if ( frequency % KOneTabInHz == 0 ) { |
737 painter.drawText( QPoint( textPosX + frequencyWidth + decimalSpace, 20 ), DECIMAL_TEXT ); |
|
738 |
|
739 } else if ( frequency % ONE_TAB_IN_HZ == 0 ) { |
677 |
740 |
678 // Draw the low frequency tab for the uneven number |
741 // Draw the low frequency tab for the uneven number |
679 painter.drawLine( makeTab( pixels, KTabHeightSmall ) ); |
742 painter.drawLine( makeTab( pixels + leftOverlap, TAB_HEIGHT_SMALL ) ); |
680 |
743 |
681 } |
744 } |
682 |
745 |
683 addFrequencyPos( startPixel + pixels + KRounder, frequency, item ); |
746 addFrequencyPos( int( startPixel + pixels + ROUNDER ), frequency, item ); |
684 } |
747 } |
685 |
748 |
686 // Draw favorites and local stations |
749 // Draw favorites and local stations |
687 favoritePen.setColor( Qt::yellow ); |
750 favoritePen.setColor( Qt::yellow ); |
688 |
751 |
689 const int markerYPos = KHeight - 20; |
752 const int markerYPos = mItemHeight - 28; |
690 foreach ( const RadioStation& station, stations ) { |
753 foreach ( const RadioStation& station, stations ) { |
691 const uint frequency = station.frequency(); |
754 const uint frequency = station.frequency(); |
692 pixels = qreal( frequency - startFrequency ) / KPixelInHz; |
755 pixels = qreal( frequency - startFrequency ) / PIXEL_IN_HZ; |
693 |
756 |
694 if ( station.isFavorite() ) { |
757 if ( station.isFavorite() ) { |
695 favoritePen.setWidth( KTabWidthFavorite ); |
758 favoritePen.setWidth( PEN_WIDTH_FAVORITE ); |
696 painter.setPen( favoritePen ); |
759 painter.setPen( favoritePen ); |
697 painter.drawEllipse( pixels - 3, markerYPos - 3, 6, 6 ); |
760 painter.drawEllipse( int( pixels + leftOverlap - 3 ), markerYPos - 3, 6, 6 ); |
698 // painter.drawPixmap( pixels - 10, 20, 20, 20, mFavoriteIcon.pixmap() ); |
|
699 } else if ( station.isType( RadioStation::LocalStation ) ) { |
761 } else if ( station.isType( RadioStation::LocalStation ) ) { |
700 // painter.setPen( normalPen ); |
|
701 // painter.drawLine( pixels, // Start X |
|
702 // KHeight - KTabHeightFavorite, // Start Y |
|
703 // pixels, // End X |
|
704 // KHeight ); // End Y |
|
705 |
762 |
706 favoritePen.setWidth( 1 ); |
763 favoritePen.setWidth( 1 ); |
707 painter.setPen( favoritePen ); |
764 painter.setPen( favoritePen ); |
708 painter.drawEllipse( pixels - 4, markerYPos - 4, 8, 8 ); |
765 painter.drawEllipse( int( pixels + leftOverlap - 4 ), markerYPos - 4, 8, 8 ); |
709 } |
766 } |
710 } |
767 } |
711 |
768 |
712 return pixmap; |
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 ); |
713 } |
778 } |
714 |
779 |
715 /*! |
780 /*! |
716 * |
781 * |
717 */ |
782 */ |
718 void RadioFrequencyStrip::emitFrequencyChanged( uint frequency ) |
783 void RadioFrequencyStrip::emitFrequencyChanged( uint frequency ) |
719 { |
784 { |
720 if ( frequency > 0 && frequency != mFrequency ) { |
785 if ( frequency > 0 && frequency != mFrequency ) { |
721 mFrequency = frequency; |
786 mFrequency = frequency; |
722 emit frequencyChanged( frequency, TuneReason::FrequencyStrip ); |
787 //TOD: Get direction |
|
788 emit frequencyChanged( frequency, TuneReason::FrequencyStrip, Scroll::Shortest ); |
723 } |
789 } |
724 } |
790 } |
725 |
791 |
726 /*! |
792 /*! |
727 * |
793 * |
728 */ |
794 */ |
729 int RadioFrequencyStrip::selectorPos() const |
795 int RadioFrequencyStrip::selectorPos() const |
730 { |
796 { |
731 const int pos = ( -contentWidget()->x() + mSelectorPos ) + KRounder; |
797 const int pos = int( -contentWidget()->x() + mSelectorPos + ROUNDER ); |
732 return pos % mMaxWidth; |
798 return pos % mMaxWidth; |
733 } |
799 } |
734 |
800 |
735 /*! |
801 /*! |
736 * |
802 * |
737 */ |
803 */ |
738 void RadioFrequencyStrip::scrollToFrequency( uint frequency, int time ) |
804 void RadioFrequencyStrip::scrollToFrequency( uint frequency, Scroll::Direction direction, int time, TuneReason::Reason reason ) |
739 { |
805 { |
740 // Find the shortest route to the requested frequency. |
806 int targetFreqPos = mFrequencies.value( frequency ).mPosition; |
741 const int pos = ( -contentWidget()->x() + mSelectorPos ) + KRounder; |
807 const int currentFreqPos = mFrequencies.value( mFrequency ).mPosition; |
742 if ( pos >= mMaxWidth - KWidth + mSeparatorPos ) { |
808 const int currentPos = int( -contentWidget()->x() + mSelectorPos + ROUNDER ); |
743 const qreal newPos = qreal( mFrequencies.value( frequency ).mPosition ) - mSelectorPos + mMaxWidth; |
809 const bool isInSecondHalf = currentPos >= mMaxWidth - ITEM_WIDTH + mSeparatorPos; |
744 scrollContentsTo( QPointF( newPos, 0 ), time ); |
810 |
745 } else { |
811 // Special case: When there is only one favorite and the user presses skip |
746 scrollContentsTo( QPointF( qreal( mFrequencies.value( frequency ).mPosition ) - mSelectorPos, 0 ), time ); |
812 // the strip must scroll around to the same frequency. |
747 } |
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 ); |
748 } |
845 } |
749 |
846 |
750 /*! |
847 /*! |
751 * |
848 * |
752 */ |
849 */ |
753 void RadioFrequencyStrip::hideButtons() |
850 void RadioFrequencyStrip::hideButtons() |
754 { |
851 { |
755 mButtonsVisible = false; |
852 HbEffect::start( mLeftButton, SLIDE_TO_LEFT ); |
756 HbEffect::start( mLeftButton, KSlideToLeft ); |
853 HbEffect::start( mRightButton, SLIDE_TO_RIGHT ); |
757 HbEffect::start( mRightButton, KSlideToRight ); |
|
758 } |
854 } |
759 |
855 |
760 /*! |
856 /*! |
761 * |
857 * |
762 */ |
858 */ |
763 void RadioFrequencyStrip::showButtons() |
859 void RadioFrequencyStrip::showButtons() |
764 { |
860 { |
765 mButtonsVisible = true; |
861 HbEffect::start( mLeftButton, SLIDE_FROM_LEFT ); |
766 HbEffect::start( mLeftButton, KSlideFromLeft ); |
862 HbEffect::start( mRightButton, SLIDE_FROM_RIGHT ); |
767 HbEffect::start( mRightButton, KSlideFromRight ); |
863 } |
768 } |
|