radioapp/radiowidgets/src/radiofrequencystrip.cpp
changeset 39 ac7857bd5fdb
parent 38 f8c3d4e6102c
child 47 74b7c6e79031
equal deleted inserted replaced
38:f8c3d4e6102c 39:ac7857bd5fdb
    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 }