radioapp/radiowidgets/src/radiostationcarousel.cpp
branchRCL_3
changeset 20 93c594350b9a
parent 19 cce62ebc198e
equal deleted inserted replaced
19:cce62ebc198e 20:93c594350b9a
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 // System includes
       
    19 #include <QGraphicsLinearLayout>
       
    20 #include <QGraphicsSceneResizeEvent>
       
    21 #include <QTimer>
       
    22 #include <HbPanGesture>
       
    23 #include <HbSwipeGesture>
       
    24 #include <HbFontSpec>
       
    25 #include <HbMenu>
       
    26 #include <QPainter>
       
    27 
       
    28 // User includes
       
    29 #include "radiostationcarousel.h"
       
    30 #include "radiocarouselanimator.h"
       
    31 #include "radiouiloader.h"
       
    32 #include "radiocarouselitem.h"
       
    33 #include "radiostation.h"
       
    34 #include "radiouiengine.h"
       
    35 #include "radiostationmodel.h"
       
    36 #include "radiofadinglabel.h"
       
    37 #include "radiologger.h"
       
    38 #include "radioutil.h"
       
    39 #include "radio_global.h"
       
    40 
       
    41 // Constants
       
    42 const int RTPLUS_CHECK_TIMEOUT = 700;
       
    43 const int INFOTEXT_NOFAVORITES_TIMEOUT = 5000;
       
    44 const int SET_FREQUENCY_TIMEOUT = 500;
       
    45 const int FAVORITE_HINT_SHOW_DELAY = 1000;
       
    46 const int FAVORITE_HINT_HIDE_DELAY = 2000;
       
    47 
       
    48 // Matti testing constants
       
    49 const QLatin1String LEFT_ITEM_NAME      ( "carousel_left" );
       
    50 const QLatin1String CENTER_ITEM_NAME    ( "carousel_center" );
       
    51 const QLatin1String RIGHT_ITEM_NAME     ( "carousel_right" );
       
    52 
       
    53 #ifdef BUILD_WIN32
       
    54 #   define SCROLLBAR_POLICY ScrollBarAlwaysOn
       
    55 #else
       
    56 #   define SCROLLBAR_POLICY ScrollBarAlwaysOff
       
    57 #endif // BUILD_WIN32
       
    58 
       
    59 #define CALL_TO_ALL_ITEMS( expr ) \
       
    60     mItems[LeftItem]->expr; \
       
    61     mItems[CenterItem]->expr; \
       
    62     mItems[RightItem]->expr;
       
    63 
       
    64 /*!
       
    65  *
       
    66  */
       
    67 RadioStationCarousel::RadioStationCarousel( QGraphicsItem* parent ) :
       
    68     HbScrollArea( parent ),
       
    69     mUiEngine( NULL ),
       
    70     mAutoScrollTime( 300 ),
       
    71     mGenericTimer( new QTimer( this ) ),
       
    72     mTimerMode( NoTimer ),
       
    73     mInfoText( NULL ),
       
    74     mRadiotextPopup( NULL ),
       
    75     mContainer( new HbWidget( this ) ),
       
    76     mMidScrollPos( 0 ),
       
    77     mMaxScrollPos( 0 ),
       
    78     mCurrentIndex( 0 ),
       
    79     mTargetIndex( -1 ),
       
    80     mIsCustomFreq( false ),
       
    81     mInfoTextType( CarouselInfoText::None ),
       
    82     mModel( NULL ),
       
    83     mPosAdjustmentDisabled( false ),
       
    84     mScrollDirection( Scroll::Shortest ),
       
    85     mManualSeekMode( false )
       
    86 #ifdef USE_DEBUGGING_CONTROLS
       
    87     ,mRdsLabel( new RadioFadingLabel( this ) )
       
    88 #endif // USE_DEBUGGING_CONTROLS
       
    89 {
       
    90 }
       
    91 
       
    92 /*!
       
    93  * Property
       
    94  *
       
    95  */
       
    96 void RadioStationCarousel::setFavoriteIcon( const HbIcon& favoriteIcon )
       
    97 {
       
    98     mFavoriteIcon = favoriteIcon;
       
    99 }
       
   100 
       
   101 /*!
       
   102  * Property
       
   103  *
       
   104  */
       
   105 HbIcon RadioStationCarousel::favoriteIcon() const
       
   106 {
       
   107     return mFavoriteIcon;
       
   108 }
       
   109 
       
   110 /*!
       
   111  * Property
       
   112  *
       
   113  */
       
   114 void RadioStationCarousel::setNonFavoriteIcon( const HbIcon& nonFavoriteIcon )
       
   115 {
       
   116     mNonFavoriteIcon = nonFavoriteIcon;
       
   117 }
       
   118 
       
   119 /*!
       
   120  * Property
       
   121  *
       
   122  */
       
   123 HbIcon RadioStationCarousel::nonFavoriteIcon() const
       
   124 {
       
   125     return mNonFavoriteIcon;
       
   126 }
       
   127 
       
   128 /*!
       
   129  *
       
   130  */
       
   131 void RadioStationCarousel::setAutoScrollTime( const int time )
       
   132 {
       
   133     mAutoScrollTime = time;
       
   134 }
       
   135 
       
   136 /*!
       
   137  *
       
   138  */
       
   139 int RadioStationCarousel::autoScrollTime() const
       
   140 {
       
   141     return mAutoScrollTime;
       
   142 }
       
   143 
       
   144 /*!
       
   145  *
       
   146  */
       
   147 void RadioStationCarousel::init( RadioUiLoader& uiLoader, RadioUiEngine* uiEngine )
       
   148 {
       
   149     mUiEngine = uiEngine;
       
   150     RadioUtil::setCarousel( this );
       
   151 
       
   152     mItems[CenterItem] = new RadioCarouselItem( *this, this, true );
       
   153     mItems[LeftItem] = new RadioCarouselItem( *this, this );
       
   154     mItems[RightItem] = new RadioCarouselItem( *this, this );
       
   155 
       
   156     // Matti testing needs the objects to have names
       
   157     mItems[LeftItem]->setObjectName( LEFT_ITEM_NAME );
       
   158     mItems[CenterItem]->setObjectName( CENTER_ITEM_NAME );
       
   159     mItems[RightItem]->setObjectName( RIGHT_ITEM_NAME );
       
   160 
       
   161     QGraphicsLinearLayout* layout = new QGraphicsLinearLayout( Qt::Horizontal );
       
   162     layout->setContentsMargins( 0, 0, 0, 0 );
       
   163     layout->setSpacing( 0 );
       
   164     layout->addItem( mItems[LeftItem] );
       
   165     layout->addItem( mItems[CenterItem] );
       
   166     layout->addItem( mItems[RightItem] );
       
   167     mContainer->setLayout( layout );
       
   168     setContentWidget( mContainer );
       
   169 
       
   170     setClampingStyle( HbScrollArea::NoClamping );
       
   171     setScrollDirections( Qt::Horizontal );
       
   172 
       
   173     setFrictionEnabled( true );
       
   174     setHorizontalScrollBarPolicy( HbScrollArea::SCROLLBAR_POLICY );
       
   175     setVerticalScrollBarPolicy( HbScrollArea::ScrollBarAlwaysOff );
       
   176 
       
   177     mInfoText = uiLoader.findWidget<HbLabel>( DOCML::MV_NAME_INFO_TEXT );
       
   178     mInfoText->setTextWrapping( Hb::TextWordWrap );
       
   179 
       
   180     mRadiotextPopup = uiLoader.findObject<HbMenu>( DOCML::MV_NAME_CAROUSEL_RT_MENU );
       
   181 
       
   182 #ifdef BUILD_WIN32
       
   183     HbFontSpec spec = mInfoText->fontSpec();
       
   184     spec.setRole( HbFontSpec::Secondary );
       
   185     mInfoText->setFontSpec( spec );
       
   186 #endif
       
   187 
       
   188     setScrollDirections( Qt::Horizontal );
       
   189 
       
   190     Radio::connect( this,           SIGNAL(scrollingEnded()),
       
   191                     this,           SLOT(adjustAfterScroll()) );
       
   192 
       
   193     mModel = &mUiEngine->stationModel();
       
   194     Radio::connect( mModel,         SIGNAL(favoriteChanged(RadioStation)),
       
   195                     this,           SLOT(update(RadioStation)) );
       
   196     Radio::connect( mModel,         SIGNAL(stationDataChanged(RadioStation)),
       
   197                     this,           SLOT(update(RadioStation)));
       
   198     Radio::connect( mModel,         SIGNAL(radioTextReceived(RadioStation)),
       
   199                     this,           SLOT(updateRadioText(RadioStation)));
       
   200     Radio::connect( mModel,         SIGNAL(dynamicPsChanged(RadioStation)),
       
   201                     this,           SLOT(update(RadioStation)));
       
   202 
       
   203     mGenericTimer->setSingleShot( true );
       
   204     Radio::connect( mGenericTimer,  SIGNAL(timeout()),
       
   205                     this,           SLOT(timerFired()));
       
   206 
       
   207     Radio::connect( mModel,         SIGNAL(rowsInserted(QModelIndex,int,int)),
       
   208                     this,           SLOT(updateStations()) );
       
   209     Radio::connect( mModel,         SIGNAL(modelReset()),
       
   210                     this,           SLOT(updateStations()) );
       
   211     Radio::connect( mModel,         SIGNAL(rowsRemoved(QModelIndex,int,int)),
       
   212                     this,           SLOT(updateStations()) );
       
   213 
       
   214     setFrequency( mUiEngine->currentFrequency(), TuneReason::Unspecified );
       
   215 
       
   216 #ifdef USE_DEBUGGING_CONTROLS
       
   217     mRdsLabel->setPos( QPoint( 300, 10 ) );
       
   218     mRdsLabel->setText( "RDS" );
       
   219     mRdsLabel->setElideMode( Qt::ElideNone );
       
   220     HbFontSpec spec = mRdsLabel->fontSpec();
       
   221     spec.setTextPaneHeight( 10 );
       
   222     spec.setRole( HbFontSpec::Secondary );
       
   223     mRdsLabel->setFontSpec( spec );
       
   224     mRdsLabel->setTextColor( Qt::gray );
       
   225     if ( mUiEngine ) {
       
   226         Radio::connect( mUiEngine,      SIGNAL(rdsAvailabilityChanged(bool)),
       
   227                         this,           SLOT(setRdsAvailable(bool)) );
       
   228     }
       
   229 #endif // USE_DEBUGGING_CONTROLS
       
   230 }
       
   231 
       
   232 /*!
       
   233  *
       
   234  */
       
   235 void RadioStationCarousel::setFrequency( uint frequency, int reason, Scroll::Direction direction )
       
   236 {
       
   237     if ( mModel ) {
       
   238         if ( !mManualSeekMode ) {
       
   239 
       
   240             if ( mModel->rowCount() <= 1 ) {
       
   241                 mItems[LeftItem]->setStation( RadioStation() );
       
   242                 mItems[RightItem]->setStation( RadioStation() );
       
   243             }
       
   244 
       
   245             mIsCustomFreq = false;
       
   246             if ( reason == TuneReason::Skip || reason == TuneReason::StationScanFinalize ) {
       
   247                 const int newIndex = mModel->indexFromFrequency( frequency );
       
   248                 scrollToIndex( newIndex, direction, NoSignal );
       
   249                 mCurrentIndex = newIndex;
       
   250             } else {
       
   251                 if ( mModel->contains( frequency ) ) {
       
   252                     mCurrentIndex = mModel->indexFromFrequency( frequency );
       
   253                 } else {
       
   254                     const RadioStation prevStation = mModel->findClosest( frequency, StationSkip::Previous );
       
   255                     if ( prevStation.isValid() ) {
       
   256                         mCurrentIndex = mModel->indexFromFrequency( prevStation.frequency() );
       
   257                     } else {
       
   258                         mCurrentIndex = -1;
       
   259                     }
       
   260 
       
   261                     mIsCustomFreq = true;
       
   262                 }
       
   263 
       
   264                 mItems[CenterItem]->setFrequency( frequency );
       
   265                 mTimerMode = SetFrequency;
       
   266                 mGenericTimer->stop();
       
   267                 mGenericTimer->start( SET_FREQUENCY_TIMEOUT );
       
   268             }
       
   269         } else {
       
   270             mItems[CenterItem]->setFrequency( frequency );
       
   271         }
       
   272     }
       
   273 }
       
   274 
       
   275 /*!
       
   276  *
       
   277  */
       
   278 RadioUiEngine* RadioStationCarousel::uiEngine()
       
   279 {
       
   280     return mUiEngine;
       
   281 }
       
   282 
       
   283 /*!
       
   284  *
       
   285  */
       
   286 bool RadioStationCarousel::isAntennaAttached() const
       
   287 {
       
   288     return mUiEngine->isAntennaAttached();
       
   289 }
       
   290 
       
   291 /*!
       
   292  *
       
   293  */
       
   294 void RadioStationCarousel::setScanningMode( bool scanning )
       
   295 {
       
   296     CALL_TO_ALL_ITEMS( setSeekLayout( scanning ) );
       
   297 
       
   298     if ( scanning ) {
       
   299         setInfoText( CarouselInfoText::Scanning );
       
   300         if ( !mAnimator ) {
       
   301             mAnimator = new RadioCarouselAnimator( *this );
       
   302         }
       
   303         mAnimator.data()->startFlashingText();
       
   304     } else {
       
   305         if ( mAnimator ) {
       
   306             mAnimator.data()->stopFlashingText();
       
   307         }
       
   308         clearInfoText();
       
   309         setCenterIndex( 0 );
       
   310         mTimerMode = FavoriteHintShow;
       
   311         mGenericTimer->start( FAVORITE_HINT_SHOW_DELAY );
       
   312     }
       
   313 
       
   314     setEnabled( !scanning );
       
   315 }
       
   316 
       
   317 /*!
       
   318  *
       
   319  */
       
   320 bool RadioStationCarousel::isInScanningMode() const
       
   321 {
       
   322     return RadioUtil::scanStatus() == Scan::ScanningInMainView;
       
   323 }
       
   324 
       
   325 /*!
       
   326  *
       
   327  */
       
   328 void RadioStationCarousel::cleanRdsData()
       
   329 {
       
   330     mItems[CenterItem]->cleanRdsData();
       
   331 }
       
   332 
       
   333 /*!
       
   334  *
       
   335  */
       
   336 void RadioStationCarousel::animateNewStation( const RadioStation& station )
       
   337 {
       
   338     if ( mAnimator && mUiEngine ) {
       
   339         const uint previousFrequency = mItems[CenterItem]->frequency();
       
   340 
       
   341         mItems[RightItem]->setFrequency( previousFrequency );
       
   342         mCurrentIndex = mModel->indexFromFrequency( station.frequency() );
       
   343 
       
   344         mAnimator.data()->startNumberScroll( previousFrequency, station.frequency() );
       
   345     }
       
   346 }
       
   347 
       
   348 /*!
       
   349  *
       
   350  */
       
   351 void RadioStationCarousel::cancelAnimation()
       
   352 {
       
   353     if ( mAnimator ) {
       
   354         mAnimator.data()->stopAll();
       
   355     }
       
   356 }
       
   357 
       
   358 /*!
       
   359  *
       
   360  */
       
   361 void RadioStationCarousel::setInfoText( CarouselInfoText::Type type )
       
   362 {
       
   363     mInfoTextType = type;
       
   364     if ( type == CarouselInfoText::NoFavorites || type == CarouselInfoText::FavoriteIconHint ) {
       
   365 //        mInfoText->setPlainText( hbTrId( "txt_rad_dialog_long_press_arrow_keys_to_search_str" ) );
       
   366     //TODO: Remove hardcoding. Temporarily hardcoded for usability testing
       
   367         mInfoText->setPlainText( "Tap star to mark favourites" );
       
   368         mInfoText->setAlignment( Qt::AlignCenter );
       
   369         mItems[CenterItem]->setItemVisibility( RadioCarouselItem::IconVisible );
       
   370         mTimerMode = InfoText;
       
   371         mGenericTimer->setInterval( INFOTEXT_NOFAVORITES_TIMEOUT );
       
   372         mGenericTimer->start();
       
   373 
       
   374         if ( !mAnimator ) {
       
   375             mAnimator = new RadioCarouselAnimator( *this );
       
   376         }
       
   377         mAnimator.data()->startFlashingIcon();
       
   378 
       
   379     } else if ( type == CarouselInfoText::ConnectAntenna ) {
       
   380         cleanRdsData();
       
   381         mInfoText->setPlainText( hbTrId( "txt_rad_info_connect_wired_headset1" ) );
       
   382         mInfoText->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
       
   383     } else if ( type == CarouselInfoText::Seeking ) {
       
   384         cleanRdsData();
       
   385         mInfoText->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
       
   386         mInfoText->setPlainText( hbTrId( "txt_rad_list_seeking" ) );
       
   387     } else if ( type == CarouselInfoText::Scanning ) {
       
   388         cleanRdsData();
       
   389         mInfoText->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
       
   390         mInfoText->setPlainText( hbTrId( "txt_rad_list_searching_all_available_stations_ple" ) );
       
   391     }
       
   392 
       
   393     mInfoText->setVisible( true );
       
   394 }
       
   395 
       
   396 /*!
       
   397  *
       
   398  */
       
   399 void RadioStationCarousel::clearInfoText()
       
   400 {
       
   401     if ( mInfoTextType != CarouselInfoText::None ) {
       
   402         if ( mAnimator ) {
       
   403             mAnimator.data()->stopFlashingIcon();
       
   404         }
       
   405 
       
   406         mGenericTimer->stop();
       
   407         mInfoTextType = CarouselInfoText::None;
       
   408         mInfoText->setVisible( false );
       
   409         mInfoText->clear();
       
   410         mItems[CenterItem]->setItemVisibility( RadioCarouselItem::AllVisible );
       
   411     }
       
   412 }
       
   413 
       
   414 /*!
       
   415  *
       
   416  */
       
   417 void RadioStationCarousel::setManualSeekMode( bool manualSeekActive )
       
   418 {
       
   419     mManualSeekMode = manualSeekActive;
       
   420     setEnabled( !manualSeekActive );
       
   421 
       
   422     mItems[CenterItem]->setSeekLayout( manualSeekActive );
       
   423     if ( !manualSeekActive ) {
       
   424         clearInfoText();
       
   425         setFrequency( mUiEngine->currentFrequency(), TuneReason::Unspecified );
       
   426     }
       
   427 }
       
   428 
       
   429 /*!
       
   430  *
       
   431  */
       
   432 void RadioStationCarousel::drawOffScreen( QPainter& painter )
       
   433 {
       
   434     mItems[CenterItem]->drawOffScreen( painter );
       
   435 }
       
   436 
       
   437 /*!
       
   438  *
       
   439  */
       
   440 void RadioStationCarousel::setLandscape( bool landscape )
       
   441 {
       
   442     CALL_TO_ALL_ITEMS( setLandscape( landscape ) );
       
   443 }
       
   444 
       
   445 /*!
       
   446  * Private slot
       
   447  *
       
   448  */
       
   449 void RadioStationCarousel::scrollPosChanged( const QPointF& newPosition )
       
   450 {
       
   451     Q_UNUSED( newPosition );
       
   452 //    const int xPos = static_cast<int>( newPosition.x() );
       
   453 //    mItems[CenterItem]->setPos( xPos - mMidScrollPos, 0 );
       
   454 }
       
   455 
       
   456 /*!
       
   457  * Private slot
       
   458  ''
       
   459  */
       
   460 void RadioStationCarousel::adjustAfterScroll()
       
   461 {
       
   462     if ( isInScanningMode() ) {
       
   463         return;
       
   464     }
       
   465 
       
   466     if ( mTargetIndex != -1 ) {
       
   467         setCenterIndex( mTargetIndex );
       
   468     }
       
   469 }
       
   470 
       
   471 /*!
       
   472  * Private slot
       
   473  *
       
   474  */
       
   475 void RadioStationCarousel::update( const RadioStation& station )
       
   476 {
       
   477     if ( !mManualSeekMode && !isInScanningMode() ) {
       
   478         for ( int i = LeftItem; i <= RightItem; ++i ) {
       
   479             if ( mItems[i]->frequency() == station.frequency() ) {
       
   480                 mItems[i]->update( &station );
       
   481             }
       
   482         }
       
   483     }
       
   484 }
       
   485 
       
   486 /*!
       
   487  * Private slot
       
   488  */
       
   489 void RadioStationCarousel::updateRadioText( const RadioStation& station )
       
   490 {
       
   491     if ( isAntennaAttached() && !isInScanningMode() ) {
       
   492         if ( station.radioText().isEmpty() ) {
       
   493             mItems[CenterItem]->setRadioText( "" );
       
   494         } else {
       
   495             mRadioTextHolder = station.radioText();
       
   496             mTimerMode = RtPlusCheck;
       
   497             mGenericTimer->stop();
       
   498             mGenericTimer->setInterval( RTPLUS_CHECK_TIMEOUT );
       
   499             mGenericTimer->start();
       
   500         }
       
   501     }
       
   502 }
       
   503 
       
   504 /*!
       
   505  * Private slot
       
   506  */
       
   507 void RadioStationCarousel::updateStations()
       
   508 {
       
   509     if ( isInScanningMode() ) {
       
   510         return;
       
   511     }
       
   512 
       
   513     setFrequency( mUiEngine->currentFrequency(), TuneReason::Unspecified );
       
   514 }
       
   515 
       
   516 /*!
       
   517  * Private slot
       
   518  */
       
   519 void RadioStationCarousel::timerFired()
       
   520 {
       
   521     if ( mTimerMode == SetFrequency ) {
       
   522         setCenterIndex( mCurrentIndex, NoSignal | IgnoreCenter );
       
   523         mTimerMode = NoTimer;
       
   524     } else if ( mTimerMode == RtPlusCheck ) {
       
   525         //mItems[CenterItem]->mRadiotextLabel->setText( mRadioTextHolder );
       
   526         mRadioTextHolder = "";
       
   527         mTimerMode = NoTimer;
       
   528     } else if ( mTimerMode == InfoText ) {
       
   529         clearInfoText();
       
   530         mTimerMode = NoTimer;
       
   531     } else if ( mTimerMode == FavoriteHintShow ) {
       
   532         setInfoText( CarouselInfoText::FavoriteIconHint );
       
   533         mTimerMode = FavoriteHintHide;
       
   534         mGenericTimer->start( FAVORITE_HINT_HIDE_DELAY );
       
   535     } else if ( mTimerMode == FavoriteHintHide ) {
       
   536         clearInfoText();
       
   537         mTimerMode = NoTimer;
       
   538     }
       
   539 }
       
   540 
       
   541 #ifdef USE_DEBUGGING_CONTROLS
       
   542 /*!
       
   543  * Public slot
       
   544  */
       
   545 void RadioStationCarousel::setRdsAvailable( bool available )
       
   546 {
       
   547     QColor color = Qt::green;
       
   548     if ( !available && mUiEngine ) {
       
   549         LOG_FORMAT( "No RDS signal: Station has sent RDS earlier: %d", mUiEngine.model().currentStation().hasSentRds() );
       
   550         color = mUiEngine.model().currentStation().hasSentRds() ? Qt::yellow : Qt::gray;
       
   551         mRdsLabel->setText( "RDS" );
       
   552     } else {
       
   553         mRdsLabel->setText( "-RDS-" );
       
   554     }
       
   555     mRdsLabel->setTextColor( color );
       
   556 }
       
   557 #endif // USE_DEBUGGING_CONTROLS
       
   558 
       
   559 /*!
       
   560  * Public slot
       
   561  */
       
   562 void RadioStationCarousel::updateAntennaStatus( bool connected )
       
   563 {
       
   564     mGenericTimer->stop();
       
   565 
       
   566     if ( !connected ) {
       
   567         setInfoText( CarouselInfoText::ConnectAntenna );
       
   568     } else {
       
   569         clearInfoText();
       
   570     }
       
   571 }
       
   572 
       
   573 /*!
       
   574  * \reimp
       
   575  */
       
   576 void RadioStationCarousel::mousePressEvent( QGraphicsSceneMouseEvent* event )
       
   577 {
       
   578     if ( mInfoTextType == CarouselInfoText::NoFavorites || mInfoTextType == CarouselInfoText::FavoriteIconHint ) {
       
   579         clearInfoText();
       
   580     }
       
   581 
       
   582     HbScrollArea::mousePressEvent( event );
       
   583 }
       
   584 
       
   585 /*!
       
   586  * \reimp
       
   587  */
       
   588 void RadioStationCarousel::resizeEvent( QGraphicsSceneResizeEvent* event )
       
   589 {
       
   590     HbScrollArea::resizeEvent( event );
       
   591 
       
   592     const int width = (int)event->newSize().width();
       
   593 
       
   594     mMidScrollPos = -width;
       
   595     mMaxScrollPos = mMidScrollPos * 2;
       
   596 
       
   597     if ( isInitialized() ) {
       
   598         mItems[LeftItem]->setMinimumWidth( width );
       
   599         mItems[CenterItem]->setMinimumWidth( width );
       
   600         mItems[RightItem]->setMinimumWidth( width );
       
   601     }
       
   602 }
       
   603 
       
   604 /*!
       
   605  * \reimp
       
   606  */
       
   607 void RadioStationCarousel::showEvent( QShowEvent* event )
       
   608 {
       
   609     HbScrollArea::showEvent( event );
       
   610 //    mContainer->setPos( mMidScrollPos, 0 );
       
   611 }
       
   612 
       
   613 /*!
       
   614  * \reimp
       
   615  */
       
   616 void RadioStationCarousel::gestureEvent( QGestureEvent* event )
       
   617 {
       
   618 //    if ( HbSwipeGesture* swipeGesture = static_cast<HbSwipeGesture*>( event->gesture( Qt::SwipeGesture ) ) ) {
       
   619 //        if ( swipeGesture->state() == Qt::GestureFinished ) {
       
   620 //            if ( swipeGesture->horizontalDirection() == QSwipeGesture::Left ) {
       
   621 //                emit skipRequested( StationSkip::Next );
       
   622 //            } else if ( swipeGesture->horizontalDirection() == QSwipeGesture::Right ) {
       
   623 //                emit skipRequested( StationSkip::Previous );
       
   624 //            }
       
   625 //            mIsCustomFreq = false;
       
   626 //        }
       
   627 //        return;
       
   628 //    }
       
   629 
       
   630     HbScrollArea::gestureEvent( event );
       
   631 
       
   632     if ( HbPanGesture* gesture = qobject_cast<HbPanGesture*>( event->gesture( Qt::PanGesture ) ) ) {
       
   633         if ( gesture->state() == Qt::GestureFinished ) {
       
   634             adjustPos( (int)gesture->offset().x() );
       
   635         }
       
   636     }
       
   637 }
       
   638 
       
   639 /*!
       
   640  * \reimp
       
   641  */
       
   642 void RadioStationCarousel::handleIconClicked( const RadioStation& station )
       
   643 {
       
   644     if ( mModel ) {
       
   645         mModel->setData( QModelIndex(), station.frequency(), RadioRole::ToggleFavoriteRole );
       
   646     }
       
   647 }
       
   648 
       
   649 /*!
       
   650  * \reimp
       
   651  */
       
   652 void RadioStationCarousel::handleRadiotextClicked( const RadioStation& station )
       
   653 {
       
   654     Q_UNUSED( station );
       
   655     mRadiotextPopup->show();
       
   656 }
       
   657 
       
   658 /*!
       
   659  * \reimp
       
   660  */
       
   661 void RadioStationCarousel::handleUrlClicked( const RadioStation& station )
       
   662 {
       
   663     mUiEngine->launchBrowser( station.url() );
       
   664 }
       
   665 
       
   666 /*!
       
   667  * \reimp
       
   668  */
       
   669 QString RadioStationCarousel::localizeGenre( int genre )
       
   670 {
       
   671     return mUiEngine->genreToString( genre, GenreTarget::Carousel );
       
   672 }
       
   673 
       
   674 /*!
       
   675  * \reimp
       
   676  */
       
   677 bool RadioStationCarousel::isInManualSeek() const
       
   678 {
       
   679     return mManualSeekMode;
       
   680 }
       
   681 
       
   682 /*!
       
   683  *
       
   684  */
       
   685 RadioStation RadioStationCarousel::findStation( uint frequency )
       
   686 {
       
   687     return mModel->findStation( frequency, FindCriteria::IncludeManualStation );
       
   688 }
       
   689 
       
   690 /*!
       
   691  *
       
   692  */
       
   693 bool RadioStationCarousel::isInitialized() const
       
   694 {
       
   695     return mUiEngine != NULL;
       
   696 }
       
   697 
       
   698 /*!
       
   699  *
       
   700  */
       
   701 void RadioStationCarousel::setCenterIndex( int index, ScrollMode mode )
       
   702 {
       
   703     Q_UNUSED( mode );
       
   704     if ( mModel ) {
       
   705         const int newIndex = trimIndex( index );
       
   706         mCurrentIndex = newIndex;
       
   707         mTargetIndex = -1;
       
   708 
       
   709         if ( !mIsCustomFreq ) {
       
   710             mItems[CenterItem]->setStation( mModel->stationAt( mCurrentIndex ) );
       
   711         }
       
   712 
       
   713         if ( mModel->rowCount() > 1 ) {
       
   714             const int leftIndex = prevIndex( mCurrentIndex );
       
   715             const int rightIndex = nextIndex( mCurrentIndex );
       
   716             mItems[LeftItem]->setStation( mModel->stationAt( leftIndex ) );
       
   717             mItems[RightItem]->setStation( mModel->stationAt( rightIndex ) );
       
   718         } else {
       
   719 
       
   720             if ( mIsCustomFreq ) {
       
   721                 const uint frequency = mItems[CenterItem]->frequency();
       
   722                 mItems[LeftItem]->setStation( mModel->findClosest( frequency, StationSkip::Previous ) );
       
   723                 mItems[RightItem]->setStation( mModel->findClosest( frequency, StationSkip::Next ) );
       
   724             } else {
       
   725                 mItems[LeftItem]->setStation( RadioStation() );
       
   726                 mItems[RightItem]->setStation( RadioStation() );
       
   727             }
       
   728         }
       
   729 
       
   730         scrollContentsTo( QPointF( -mMidScrollPos /* + delta */, 0 ), 0 );
       
   731 
       
   732 //        if ( !mode.testFlag( NoSignal ) ) {
       
   733 //            uint frequency = mModel->stationAt( mCurrentIndex ).frequency();
       
   734 //            emit frequencyChanged( frequency, TuneReason::StationCarousel, mScrollDirection );
       
   735 //            mScrollDirection = Scroll::Shortest;
       
   736 //        }
       
   737     }
       
   738 }
       
   739 
       
   740 /*!
       
   741  *
       
   742  */
       
   743 void RadioStationCarousel::scrollToIndex( int index, Scroll::Direction direction, ScrollMode mode )
       
   744 {
       
   745     if ( mModel && index >= 0  ) {
       
   746         mTargetIndex = index;
       
   747         const int difference = calculateDifference( index, direction );
       
   748         int scrollTime = mAutoScrollTime;
       
   749 
       
   750         int posX = direction == Scroll::Left ? -mMaxScrollPos : 0;
       
   751         if ( difference == 1 ) {
       
   752             if ( direction == Scroll::Right ) {
       
   753                 posX = 0;
       
   754             } else if ( direction == Scroll::Left ) {
       
   755                 posX = -mMaxScrollPos;
       
   756             }
       
   757         } else {
       
   758             if ( direction == Scroll::Right ) {
       
   759                 // Item where the scrolling starts
       
   760                 mItems[RightItem]->setStation( mModel->stationAt( mCurrentIndex ) );
       
   761 
       
   762                 // Item that is skipped over
       
   763                 const uint centerFreq = mModel->stationAt( nextIndex( index ) ).frequency();
       
   764                 mItems[CenterItem]->setFrequency( centerFreq );
       
   765 
       
   766                 // Item where the scrolling ends
       
   767                 const RadioStation station = mModel->stationAt( index );
       
   768                 mItems[LeftItem]->setStation( station );
       
   769 
       
   770                 mContainer->setPos( mMaxScrollPos, 0 );
       
   771                 posX = 0;
       
   772             } else if ( direction == Scroll::Left ) {
       
   773                 // Item where the scrolling starts
       
   774                 mItems[LeftItem]->setStation( mModel->stationAt( mCurrentIndex ) );
       
   775 
       
   776                 // Item that is skipped over
       
   777                 const uint centerFreq = mModel->stationAt( prevIndex( index ) ).frequency();
       
   778                 mItems[CenterItem]->setFrequency( centerFreq );
       
   779 
       
   780                 // Item where the scrolling ends
       
   781                 const RadioStation station = mModel->stationAt( index );
       
   782                 mItems[RightItem]->setStation( station );
       
   783 
       
   784                 mContainer->setPos( 0, 0 );
       
   785                 posX = -mMaxScrollPos;
       
   786             }
       
   787         }
       
   788 
       
   789         if ( mode.testFlag( UpdateItem ) ) {
       
   790             //item->update();
       
   791         }
       
   792 
       
   793         if ( mode.testFlag( NoAnim ) ) {
       
   794             scrollTime = 0;
       
   795         } else if ( mode.testFlag( FromPanGesture ) ) {
       
   796             scrollTime = 500;
       
   797         } else if ( mode.testFlag( FromSwipeGesture ) ) {
       
   798             scrollTime = 100;
       
   799         }
       
   800 
       
   801         scrollContentsTo( QPointF( posX, 0 ), scrollTime );
       
   802     }
       
   803 }
       
   804 
       
   805 /*!
       
   806  *
       
   807  */
       
   808 int RadioStationCarousel::calculateDifference( int targetIndex, Scroll::Direction& direction )
       
   809 {
       
   810     int difference = 0;
       
   811     const int rowCount = mModel->rowCount();
       
   812 
       
   813     int diffToLeft = 0;
       
   814     int diffToRight = 0;
       
   815     if ( targetIndex > mCurrentIndex ) {
       
   816         const int loopedDiff = mCurrentIndex + rowCount - targetIndex;
       
   817         const int directDiff = targetIndex - mCurrentIndex;
       
   818         diffToLeft = loopedDiff;
       
   819         diffToRight = directDiff;
       
   820     } else {
       
   821         const int loopedDiff = targetIndex + rowCount - mCurrentIndex;
       
   822         const int directDiff = mIsCustomFreq ? 1 : mCurrentIndex - targetIndex;
       
   823         diffToLeft = directDiff;
       
   824         diffToRight = loopedDiff;
       
   825     }
       
   826 
       
   827     if ( direction == Scroll::Right ) {
       
   828         difference = diffToLeft;
       
   829     } else if ( direction == Scroll::Left ) {
       
   830         difference = diffToRight;
       
   831     } else {
       
   832         if ( diffToLeft < diffToRight ) {
       
   833             difference = diffToLeft;
       
   834             direction = Scroll::Right;
       
   835         } else {
       
   836             difference = diffToRight;
       
   837             direction = Scroll::Left;
       
   838         }
       
   839     }
       
   840 
       
   841     return difference;
       
   842 }
       
   843 
       
   844 /*!
       
   845  *
       
   846  */
       
   847 bool RadioStationCarousel::isScrollingAllowed() const
       
   848 {
       
   849     const int rowCount = mModel->rowCount();
       
   850     return rowCount > 1 || ( rowCount == 1 && mIsCustomFreq );
       
   851 }
       
   852 
       
   853 /*!
       
   854  *
       
   855  */
       
   856 void RadioStationCarousel::adjustPos( int offset )
       
   857 {
       
   858     int newPos = mMidScrollPos;
       
   859     const int threshold = (int)size().width() / 5;
       
   860     int newIndex = mCurrentIndex;
       
   861     bool needsToScroll = false;
       
   862 
       
   863     if ( isScrollingAllowed() && abs( offset ) >= threshold ) {
       
   864         needsToScroll = true;
       
   865         if ( offset > 0 ) {
       
   866             newPos = 0;
       
   867             mScrollDirection = Scroll::Right;
       
   868             if ( !mIsCustomFreq ) {
       
   869                 const uint newFreq = mModel->findClosest( mItems[CenterItem]->frequency(), StationSkip::PreviousFavorite ).frequency();
       
   870                 if ( newFreq > 0 ) {
       
   871                     newIndex = mModel->indexFromFrequency( newFreq );
       
   872                 } else {
       
   873                     needsToScroll = false;
       
   874                     newPos = mMidScrollPos;
       
   875                 }
       
   876             }
       
   877         } else {
       
   878             mScrollDirection = Scroll::Left;
       
   879             newPos = mMaxScrollPos;
       
   880 
       
   881             const uint newFreq = mModel->findClosest( mItems[CenterItem]->frequency(), StationSkip::NextFavorite ).frequency();
       
   882             if ( newFreq > 0 ) {
       
   883                 newIndex = mModel->indexFromFrequency( newFreq );
       
   884             } else {
       
   885                 needsToScroll = false;
       
   886                 newPos = mMidScrollPos;
       
   887             }
       
   888         }
       
   889     }
       
   890 
       
   891     newIndex = trimIndex( newIndex );
       
   892     if ( needsToScroll ) {
       
   893         const uint frequency = mModel->stationAt( newIndex ).frequency();
       
   894         emit frequencyChanged( frequency, TuneReason::StationCarousel, mScrollDirection );
       
   895         scrollToIndex( newIndex, mScrollDirection, RadioStationCarousel::FromPanGesture );
       
   896         mIsCustomFreq = false;
       
   897     } else {
       
   898         scrollContentsTo( QPointF( -newPos, 0 ), 300 );
       
   899     }
       
   900 }
       
   901 
       
   902 /*!
       
   903  *
       
   904  */
       
   905 int RadioStationCarousel::trimIndex( int index )
       
   906 {
       
   907     const int count = mModel ? mModel->rowCount() : 0;
       
   908 
       
   909     if ( count == 0 ) {
       
   910         return -1;
       
   911     }
       
   912 
       
   913     if ( index < 0 ) {
       
   914         index = count - 1;
       
   915     }
       
   916     index %= count;
       
   917     return index;
       
   918 }
       
   919 
       
   920 /*!
       
   921  *
       
   922  */
       
   923 int RadioStationCarousel::prevIndex( int index )
       
   924 {
       
   925     if ( !mIsCustomFreq ) {
       
   926         --index;
       
   927     }
       
   928     return trimIndex( index );
       
   929 }
       
   930 
       
   931 /*!
       
   932  *
       
   933  */
       
   934 int RadioStationCarousel::nextIndex( int index )
       
   935 {
       
   936     return trimIndex( index + 1 );
       
   937 }
       
   938 
       
   939 /*!
       
   940  *
       
   941  */
       
   942 void RadioStationCarousel::skip( StationSkip::Mode mode )
       
   943 {
       
   944     if ( mModel ) {
       
   945         const uint frequency = mModel->findClosest( mItems[CenterItem]->frequency(), mode ).frequency();
       
   946         const int index = mModel->indexFromFrequency( frequency );
       
   947         const Scroll::Direction direction = RadioUtil::scrollDirectionFromSkipMode( mode );
       
   948         scrollToIndex( index, direction, RadioStationCarousel::NoSignal );
       
   949     }
       
   950 }